blob: d1b83d16bfc7fd15b9a032d09e69eda1a6a57b24 [file] [log] [blame]
Marc Slemko66949872006-07-15 01:52:39 +00001#include "Monitor.h"
2
3#include <assert.h>
4#include <errno.h>
5#include <pthread.h>
6
7namespace facebook { namespace thrift { namespace concurrency {
8
9/** Monitor implementation using the POSIX pthread library
10
11 @author marc
12 @version $Id$ */
13
14class Monitor::Impl {
15
16 public:
17
18 Impl() :
19 mutexInitialized(false) {
20
21 /* XXX
22 Need to fix this to handle failures without leaking. */
23
24 assert(pthread_mutex_init(&_pthread_mutex, NULL) == 0);
25
26 mutexInitialized = true;
27
28 assert(pthread_cond_init(&_pthread_cond, NULL) == 0);
29 }
30
31 ~Impl() {
32
33 if(mutexInitialized) {
34
35 mutexInitialized = false;
36
37 assert(pthread_mutex_destroy(&_pthread_mutex) == 0);
38 }
39
40 if(condInitialized) {
41
42 condInitialized = false;
43
44 assert(pthread_cond_destroy(&_pthread_cond) == 0);
45 }
46 }
47
48 void lock() const {pthread_mutex_lock(&_pthread_mutex);}
49
50 void unlock() const {pthread_mutex_unlock(&_pthread_mutex);}
51
52 void wait(long long timeout) const {
53
54 // XXX Need to assert that caller owns mutex
55
56 if(timeout == 0LL) {
57
58 pthread_cond_wait(&_pthread_cond, &_pthread_mutex);
59
60 } else {
61
62 struct timespec abstime;
63
64 toAbsoluteTimespec(abstime, timeout);
65
66 int result = pthread_cond_timedwait(&_pthread_cond, &_pthread_mutex, &abstime);
67
68 if(result == ETIMEDOUT) {
69
70 // XXX If result is timeout need to throw timeout exception
71 }
72 }
73 }
74
75 void notify() {
76
77 // XXX Need to assert that caller owns mutex
78
79 assert(pthread_cond_signal(&_pthread_cond) == 0);
80 }
81
82 void notifyAll() {
83
84 // XXX Need to assert that caller owns mutex
85
86 assert(pthread_cond_broadcast(&_pthread_cond) == 0);
87 }
88
89private:
90
91 /** Converts relative timeout specified as a duration in milliseconds to a struct timespec structure
92 specifying current time plus timeout
93
94 @param timeout time to delay in milliseconds
95 @return struct timespec current time plus timeout */
96
97 static const void toAbsoluteTimespec(struct timespec& result, long long timeout) {
98
99 // XXX Darwin doesn't seem to have any readily useable hi-res clock.
100
101 time_t seconds;
102
103 assert(time(&seconds) != (time_t)-1);
104
105 seconds+= (timeout / 1000);
106
107 long nanoseconds = (timeout % 1000) * 1000000;
108
109 result.tv_sec = seconds + (nanoseconds / 1000000000);
110
111 result.tv_nsec = nanoseconds % 1000000000;
112 }
113
114 mutable pthread_mutex_t _pthread_mutex;
115
116 mutable bool mutexInitialized;
117
118 mutable pthread_cond_t _pthread_cond;
119
120 mutable bool condInitialized;
121};
122
123Monitor::Monitor() : _impl(new Monitor::Impl()) {}
124
125 Monitor::~Monitor() { delete _impl;}
126
127void Monitor::lock() const {_impl->lock();}
128
129void Monitor::unlock() const {_impl->unlock();}
130
131void Monitor::wait(long long timeout) const {_impl->wait(timeout);}
132
133void Monitor::notify() const {_impl->notify();}
134
135void Monitor::notifyAll() const {_impl->notifyAll();}
136
137}}} // facebook::thrift::concurrency
138