blob: 2055caa950be9bf4dc8b3c86f756fd7a6d77235f [file] [log] [blame]
Gavin McDonald0b75e1a2010-10-28 02:12:01 +00001/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19
20#include "Monitor.h"
21#include "Exception.h"
22#include "Util.h"
23
24#include <assert.h>
25#include <errno.h>
26
27#include <iostream>
28
29#include <pthread.h>
30
31namespace apache { namespace thrift { namespace concurrency {
32
33/**
34 * Monitor implementation using the POSIX pthread library
35 *
36 * @version $Id:$
37 */
38class Monitor::Impl {
39
40 public:
41
42 Impl() :
43 mutexInitialized_(false),
44 condInitialized_(false) {
45
46 if (pthread_mutex_init(&pthread_mutex_, NULL) == 0) {
47 mutexInitialized_ = true;
48
49 if (pthread_cond_init(&pthread_cond_, NULL) == 0) {
50 condInitialized_ = true;
51 }
52 }
53
54 if (!mutexInitialized_ || !condInitialized_) {
55 cleanup();
56 throw SystemResourceException();
57 }
58 }
59
60 ~Impl() { cleanup(); }
61
62 void lock() const { pthread_mutex_lock(&pthread_mutex_); }
63
64 void unlock() const { pthread_mutex_unlock(&pthread_mutex_); }
65
66 void wait(int64_t timeout) const {
67
68 // XXX Need to assert that caller owns mutex
69 assert(timeout >= 0LL);
70 if (timeout == 0LL) {
71 int iret = pthread_cond_wait(&pthread_cond_, &pthread_mutex_);
72 assert(iret == 0);
73 } else {
74 struct timespec abstime;
75 int64_t now = Util::currentTime();
76 Util::toTimespec(abstime, now + timeout);
77 int result = pthread_cond_timedwait(&pthread_cond_,
78 &pthread_mutex_,
79 &abstime);
80 if (result == ETIMEDOUT) {
81 // pthread_cond_timedwait has been observed to return early on
82 // various platforms, so comment out this assert.
83 //assert(Util::currentTime() >= (now + timeout));
84 throw TimedOutException();
85 }
86 }
87 }
88
89 void notify() {
90 // XXX Need to assert that caller owns mutex
91 int iret = pthread_cond_signal(&pthread_cond_);
92 assert(iret == 0);
93 }
94
95 void notifyAll() {
96 // XXX Need to assert that caller owns mutex
97 int iret = pthread_cond_broadcast(&pthread_cond_);
98 assert(iret == 0);
99 }
100
101 private:
102
103 void cleanup() {
104 if (mutexInitialized_) {
105 mutexInitialized_ = false;
106 int iret = pthread_mutex_destroy(&pthread_mutex_);
107 assert(iret == 0);
108 }
109
110 if (condInitialized_) {
111 condInitialized_ = false;
112 int iret = pthread_cond_destroy(&pthread_cond_);
113 assert(iret == 0);
114 }
115 }
116
117 mutable pthread_mutex_t pthread_mutex_;
118 mutable bool mutexInitialized_;
119 mutable pthread_cond_t pthread_cond_;
120 mutable bool condInitialized_;
121};
122
123Monitor::Monitor() : impl_(new Monitor::Impl()) {}
124
125Monitor::~Monitor() { delete impl_; }
126
127void Monitor::lock() const { impl_->lock(); }
128
129void Monitor::unlock() const { impl_->unlock(); }
130
131void Monitor::wait(int64_t timeout) const { impl_->wait(timeout); }
132
133void Monitor::notify() const { impl_->notify(); }
134
135void Monitor::notifyAll() const { impl_->notifyAll(); }
136
137}}} // apache::thrift::concurrency