blob: 7493ec398c564052ec953050551a586f22ec22b9 [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() :
Marc Slemko6f038a72006-08-03 18:58:09 +000025 mutexInitialized(false),
26 condInitialized(false) {
Marc Slemko66949872006-07-15 01:52:39 +000027
Marc Slemko6f038a72006-08-03 18:58:09 +000028 try {
Marc Slemko66949872006-07-15 01:52:39 +000029
Marc Slemko6f038a72006-08-03 18:58:09 +000030 assert(pthread_mutex_init(&_pthread_mutex, NULL) == 0);
Marc Slemko66949872006-07-15 01:52:39 +000031
Marc Slemko6f038a72006-08-03 18:58:09 +000032 mutexInitialized = true;
Marc Slemko66949872006-07-15 01:52:39 +000033
Marc Slemko6f038a72006-08-03 18:58:09 +000034 assert(pthread_cond_init(&_pthread_cond, NULL) == 0);
Marc Slemko66949872006-07-15 01:52:39 +000035
Marc Slemko6f038a72006-08-03 18:58:09 +000036 condInitialized = true;
Marc Slemko66949872006-07-15 01:52:39 +000037
Marc Slemko6f038a72006-08-03 18:58:09 +000038 } catch(...) {
39 cleanup();
Marc Slemko66949872006-07-15 01:52:39 +000040 }
41 }
42
Marc Slemko6f038a72006-08-03 18:58:09 +000043 ~Impl() {cleanup();}
44
Marc Slemko66949872006-07-15 01:52:39 +000045 void lock() const {pthread_mutex_lock(&_pthread_mutex);}
46
47 void unlock() const {pthread_mutex_unlock(&_pthread_mutex);}
48
49 void wait(long long timeout) const {
50
51 // XXX Need to assert that caller owns mutex
52
Marc Slemko9f27a4e2006-07-19 20:02:22 +000053 assert(timeout >= 0LL);
54
Marc Slemko66949872006-07-15 01:52:39 +000055 if(timeout == 0LL) {
56
Marc Slemko8a40a762006-07-19 17:46:50 +000057 assert(pthread_cond_wait(&_pthread_cond, &_pthread_mutex) == 0);
Marc Slemko66949872006-07-15 01:52:39 +000058
59 } else {
60
61 struct timespec abstime;
62
Marc Slemko9f27a4e2006-07-19 20:02:22 +000063 long long now = Util::currentTime();
64
65 Util::toTimespec(abstime, now + timeout);
66
Marc Slemko66949872006-07-15 01:52:39 +000067 int result = pthread_cond_timedwait(&_pthread_cond, &_pthread_mutex, &abstime);
68
69 if(result == ETIMEDOUT) {
70
Marc Slemko9f27a4e2006-07-19 20:02:22 +000071 assert(Util::currentTime() >= (now + timeout));
Marc Slemko66949872006-07-15 01:52:39 +000072 }
73 }
74 }
75
76 void notify() {
77
78 // XXX Need to assert that caller owns mutex
79
80 assert(pthread_cond_signal(&_pthread_cond) == 0);
81 }
82
83 void notifyAll() {
84
85 // XXX Need to assert that caller owns mutex
86
87 assert(pthread_cond_broadcast(&_pthread_cond) == 0);
88 }
89
90private:
91
Marc Slemko6f038a72006-08-03 18:58:09 +000092 void cleanup() {
93
94 if(mutexInitialized) {
95
96 mutexInitialized = false;
97
98 assert(pthread_mutex_destroy(&_pthread_mutex) == 0);
99 }
100
101 if(condInitialized) {
102
103 condInitialized = false;
104
105 assert(pthread_cond_destroy(&_pthread_cond) == 0);
106 }
107 }
108
Marc Slemko66949872006-07-15 01:52:39 +0000109 mutable pthread_mutex_t _pthread_mutex;
110
111 mutable bool mutexInitialized;
112
113 mutable pthread_cond_t _pthread_cond;
114
115 mutable bool condInitialized;
116};
117
118Monitor::Monitor() : _impl(new Monitor::Impl()) {}
119
Marc Slemko8a40a762006-07-19 17:46:50 +0000120Monitor::~Monitor() { delete _impl;}
Marc Slemko66949872006-07-15 01:52:39 +0000121
122void Monitor::lock() const {_impl->lock();}
123
124void Monitor::unlock() const {_impl->unlock();}
125
126void Monitor::wait(long long timeout) const {_impl->wait(timeout);}
127
128void Monitor::notify() const {_impl->notify();}
129
130void Monitor::notifyAll() const {_impl->notifyAll();}
131
132}}} // facebook::thrift::concurrency
133