blob: 518c77f1cf55cd03cd42d6dc45f0a2c0a9c37e66 [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
12namespace facebook { namespace thrift { namespace concurrency {
13
Mark Sleef5f2be42006-09-05 21:05:31 +000014/**
15 * Monitor implementation using the POSIX pthread library
16 *
17 * @author marc
18 * @version $Id:$
19 */
Marc Slemko66949872006-07-15 01:52:39 +000020class Monitor::Impl {
21
22 public:
23
Mark Sleef5f2be42006-09-05 21:05:31 +000024 Impl() :
Mark Slee2f6404d2006-10-10 01:37:40 +000025 mutexInitialized_(false),
26 condInitialized_(false) {
Marc Slemko66949872006-07-15 01:52:39 +000027
Marc Slemko6f038a72006-08-03 18:58:09 +000028 try {
Mark Slee2f6404d2006-10-10 01:37:40 +000029 assert(pthread_mutex_init(&pthread_mutex_, NULL) == 0);
30 mutexInitialized_ = true;
31 assert(pthread_cond_init(&pthread_cond_, NULL) == 0);
32 condInitialized_ = true;
Marc Slemko6f038a72006-08-03 18:58:09 +000033 } catch(...) {
34 cleanup();
Marc Slemko66949872006-07-15 01:52:39 +000035 }
36 }
37
Mark Sleef5f2be42006-09-05 21:05:31 +000038 ~Impl() { cleanup(); }
Marc Slemko6f038a72006-08-03 18:58:09 +000039
Mark Slee2f6404d2006-10-10 01:37:40 +000040 void lock() const { pthread_mutex_lock(&pthread_mutex_); }
Marc Slemko66949872006-07-15 01:52:39 +000041
Mark Slee2f6404d2006-10-10 01:37:40 +000042 void unlock() const { pthread_mutex_unlock(&pthread_mutex_); }
Marc Slemko66949872006-07-15 01:52:39 +000043
44 void wait(long long timeout) const {
45
46 // XXX Need to assert that caller owns mutex
Marc Slemko9f27a4e2006-07-19 20:02:22 +000047 assert(timeout >= 0LL);
Mark Sleef5f2be42006-09-05 21:05:31 +000048 if (timeout == 0LL) {
Mark Slee2f6404d2006-10-10 01:37:40 +000049 assert(pthread_cond_wait(&pthread_cond_, &pthread_mutex_) == 0);
Marc Slemko66949872006-07-15 01:52:39 +000050 } else {
Marc Slemko66949872006-07-15 01:52:39 +000051 struct timespec abstime;
Marc Slemko9f27a4e2006-07-19 20:02:22 +000052 long long now = Util::currentTime();
Marc Slemko9f27a4e2006-07-19 20:02:22 +000053 Util::toTimespec(abstime, now + timeout);
Mark Slee2f6404d2006-10-10 01:37:40 +000054 int result = pthread_cond_timedwait(&pthread_cond_,
55 &pthread_mutex_,
56 &abstime);
Mark Sleef5f2be42006-09-05 21:05:31 +000057 if (result == ETIMEDOUT) {
Marc Slemko9f27a4e2006-07-19 20:02:22 +000058 assert(Util::currentTime() >= (now + timeout));
Marc Slemko66949872006-07-15 01:52:39 +000059 }
60 }
61 }
62
63 void notify() {
Marc Slemko66949872006-07-15 01:52:39 +000064 // XXX Need to assert that caller owns mutex
Mark Slee2f6404d2006-10-10 01:37:40 +000065 assert(pthread_cond_signal(&pthread_cond_) == 0);
Marc Slemko66949872006-07-15 01:52:39 +000066 }
67
68 void notifyAll() {
Marc Slemko66949872006-07-15 01:52:39 +000069 // XXX Need to assert that caller owns mutex
Mark Slee2f6404d2006-10-10 01:37:40 +000070 assert(pthread_cond_broadcast(&pthread_cond_) == 0);
Marc Slemko66949872006-07-15 01:52:39 +000071 }
72
Mark Sleef5f2be42006-09-05 21:05:31 +000073 private:
Marc Slemko66949872006-07-15 01:52:39 +000074
Marc Slemko6f038a72006-08-03 18:58:09 +000075 void cleanup() {
Mark Slee2f6404d2006-10-10 01:37:40 +000076 if (mutexInitialized_) {
77 mutexInitialized_ = false;
78 assert(pthread_mutex_destroy(&pthread_mutex_) == 0);
Marc Slemko6f038a72006-08-03 18:58:09 +000079 }
80
Mark Slee2f6404d2006-10-10 01:37:40 +000081 if (condInitialized_) {
82 condInitialized_ = false;
83 assert(pthread_cond_destroy(&pthread_cond_) == 0);
Marc Slemko6f038a72006-08-03 18:58:09 +000084 }
85 }
86
Mark Slee2f6404d2006-10-10 01:37:40 +000087 mutable pthread_mutex_t pthread_mutex_;
88 mutable bool mutexInitialized_;
89 mutable pthread_cond_t pthread_cond_;
90 mutable bool condInitialized_;
Marc Slemko66949872006-07-15 01:52:39 +000091};
92
Mark Slee2f6404d2006-10-10 01:37:40 +000093Monitor::Monitor() : impl_(new Monitor::Impl()) {}
Marc Slemko66949872006-07-15 01:52:39 +000094
Mark Slee2f6404d2006-10-10 01:37:40 +000095Monitor::~Monitor() { delete impl_; }
Marc Slemko66949872006-07-15 01:52:39 +000096
Mark Slee2f6404d2006-10-10 01:37:40 +000097void Monitor::lock() const { impl_->lock(); }
Marc Slemko66949872006-07-15 01:52:39 +000098
Mark Slee2f6404d2006-10-10 01:37:40 +000099void Monitor::unlock() const { impl_->unlock(); }
Marc Slemko66949872006-07-15 01:52:39 +0000100
Mark Slee2f6404d2006-10-10 01:37:40 +0000101void Monitor::wait(long long timeout) const { impl_->wait(timeout); }
Marc Slemko66949872006-07-15 01:52:39 +0000102
Mark Slee2f6404d2006-10-10 01:37:40 +0000103void Monitor::notify() const { impl_->notify(); }
Marc Slemko66949872006-07-15 01:52:39 +0000104
Mark Slee2f6404d2006-10-10 01:37:40 +0000105void Monitor::notifyAll() const { impl_->notifyAll(); }
Marc Slemko66949872006-07-15 01:52:39 +0000106
107}}} // facebook::thrift::concurrency