blob: b1d7b726ac2e5f1e58677c78ac977ed2b049a089 [file] [log] [blame]
Marc Slemko66949872006-07-15 01:52:39 +00001#include "Monitor.h"
Marc Slemko8a40a762006-07-19 17:46:50 +00002#include "Exception.h"
Marc Slemko0e53ccd2006-07-17 23:51:05 +00003#include "Util.h"
Marc Slemko66949872006-07-15 01:52:39 +00004
5#include <assert.h>
6#include <errno.h>
Marc Slemko8a40a762006-07-19 17:46:50 +00007
8#include <iostream>
9
Marc Slemko66949872006-07-15 01:52:39 +000010#include <pthread.h>
11
Marc Slemko0e53ccd2006-07-17 23:51:05 +000012
Marc Slemko66949872006-07-15 01:52:39 +000013namespace facebook { namespace thrift { namespace concurrency {
14
15/** Monitor implementation using the POSIX pthread library
16
17 @author marc
Marc Slemko0e53ccd2006-07-17 23:51:05 +000018 @version $Id:$ */
Marc Slemko66949872006-07-15 01:52:39 +000019
20class Monitor::Impl {
21
22 public:
23
24 Impl() :
25 mutexInitialized(false) {
26
27 /* XXX
28 Need to fix this to handle failures without leaking. */
29
30 assert(pthread_mutex_init(&_pthread_mutex, NULL) == 0);
31
32 mutexInitialized = true;
33
34 assert(pthread_cond_init(&_pthread_cond, NULL) == 0);
35 }
36
37 ~Impl() {
38
39 if(mutexInitialized) {
40
41 mutexInitialized = false;
42
43 assert(pthread_mutex_destroy(&_pthread_mutex) == 0);
44 }
45
46 if(condInitialized) {
47
48 condInitialized = false;
49
50 assert(pthread_cond_destroy(&_pthread_cond) == 0);
51 }
52 }
53
54 void lock() const {pthread_mutex_lock(&_pthread_mutex);}
55
56 void unlock() const {pthread_mutex_unlock(&_pthread_mutex);}
57
58 void wait(long long timeout) const {
59
60 // XXX Need to assert that caller owns mutex
61
Marc Slemko9f27a4e2006-07-19 20:02:22 +000062 assert(timeout >= 0LL);
63
Marc Slemko66949872006-07-15 01:52:39 +000064 if(timeout == 0LL) {
65
Marc Slemko8a40a762006-07-19 17:46:50 +000066 assert(pthread_cond_wait(&_pthread_cond, &_pthread_mutex) == 0);
Marc Slemko66949872006-07-15 01:52:39 +000067
68 } else {
69
70 struct timespec abstime;
71
Marc Slemko9f27a4e2006-07-19 20:02:22 +000072 long long now = Util::currentTime();
73
74 Util::toTimespec(abstime, now + timeout);
75
Marc Slemko66949872006-07-15 01:52:39 +000076 int result = pthread_cond_timedwait(&_pthread_cond, &_pthread_mutex, &abstime);
77
78 if(result == ETIMEDOUT) {
79
Marc Slemko9f27a4e2006-07-19 20:02:22 +000080 assert(Util::currentTime() >= (now + timeout));
Marc Slemko66949872006-07-15 01:52:39 +000081 }
82 }
83 }
84
85 void notify() {
86
87 // XXX Need to assert that caller owns mutex
88
89 assert(pthread_cond_signal(&_pthread_cond) == 0);
90 }
91
92 void notifyAll() {
93
94 // XXX Need to assert that caller owns mutex
95
96 assert(pthread_cond_broadcast(&_pthread_cond) == 0);
97 }
98
99private:
100
Marc Slemko66949872006-07-15 01:52:39 +0000101 mutable pthread_mutex_t _pthread_mutex;
102
103 mutable bool mutexInitialized;
104
105 mutable pthread_cond_t _pthread_cond;
106
107 mutable bool condInitialized;
108};
109
110Monitor::Monitor() : _impl(new Monitor::Impl()) {}
111
Marc Slemko8a40a762006-07-19 17:46:50 +0000112Monitor::~Monitor() { delete _impl;}
Marc Slemko66949872006-07-15 01:52:39 +0000113
114void Monitor::lock() const {_impl->lock();}
115
116void Monitor::unlock() const {_impl->unlock();}
117
118void Monitor::wait(long long timeout) const {_impl->wait(timeout);}
119
120void Monitor::notify() const {_impl->notify();}
121
122void Monitor::notifyAll() const {_impl->notifyAll();}
123
124}}} // facebook::thrift::concurrency
125