blob: 57532a3c9f60c3bf7d0d269ed8ed9b3c69ac9bc0 [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() :
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 Slemko6f038a72006-08-03 18:58:09 +000029 assert(pthread_mutex_init(&_pthread_mutex, NULL) == 0);
Marc Slemko6f038a72006-08-03 18:58:09 +000030 mutexInitialized = true;
Marc Slemko6f038a72006-08-03 18:58:09 +000031 assert(pthread_cond_init(&_pthread_cond, NULL) == 0);
Marc Slemko6f038a72006-08-03 18:58:09 +000032 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 Sleef5f2be42006-09-05 21:05:31 +000040 void lock() const { pthread_mutex_lock(&_pthread_mutex); }
Marc Slemko66949872006-07-15 01:52:39 +000041
Mark Sleef5f2be42006-09-05 21:05:31 +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) {
Marc Slemko8a40a762006-07-19 17:46:50 +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 Sleef5f2be42006-09-05 21:05:31 +000054 int result = pthread_cond_timedwait(&_pthread_cond, &_pthread_mutex, &abstime);
55 if (result == ETIMEDOUT) {
Marc Slemko9f27a4e2006-07-19 20:02:22 +000056 assert(Util::currentTime() >= (now + timeout));
Marc Slemko66949872006-07-15 01:52:39 +000057 }
58 }
59 }
60
61 void notify() {
Marc Slemko66949872006-07-15 01:52:39 +000062 // XXX Need to assert that caller owns mutex
Marc Slemko66949872006-07-15 01:52:39 +000063 assert(pthread_cond_signal(&_pthread_cond) == 0);
64 }
65
66 void notifyAll() {
Marc Slemko66949872006-07-15 01:52:39 +000067 // XXX Need to assert that caller owns mutex
Marc Slemko66949872006-07-15 01:52:39 +000068 assert(pthread_cond_broadcast(&_pthread_cond) == 0);
69 }
70
Mark Sleef5f2be42006-09-05 21:05:31 +000071 private:
Marc Slemko66949872006-07-15 01:52:39 +000072
Marc Slemko6f038a72006-08-03 18:58:09 +000073 void cleanup() {
Mark Sleef5f2be42006-09-05 21:05:31 +000074 if (mutexInitialized) {
Marc Slemko6f038a72006-08-03 18:58:09 +000075 mutexInitialized = false;
Marc Slemko6f038a72006-08-03 18:58:09 +000076 assert(pthread_mutex_destroy(&_pthread_mutex) == 0);
77 }
78
Mark Sleef5f2be42006-09-05 21:05:31 +000079 if (condInitialized) {
Marc Slemko6f038a72006-08-03 18:58:09 +000080 condInitialized = false;
Marc Slemko6f038a72006-08-03 18:58:09 +000081 assert(pthread_cond_destroy(&_pthread_cond) == 0);
82 }
83 }
84
Marc Slemko66949872006-07-15 01:52:39 +000085 mutable pthread_mutex_t _pthread_mutex;
Marc Slemko66949872006-07-15 01:52:39 +000086 mutable bool mutexInitialized;
Marc Slemko66949872006-07-15 01:52:39 +000087 mutable pthread_cond_t _pthread_cond;
Marc Slemko66949872006-07-15 01:52:39 +000088 mutable bool condInitialized;
89};
90
91Monitor::Monitor() : _impl(new Monitor::Impl()) {}
92
Mark Sleef5f2be42006-09-05 21:05:31 +000093Monitor::~Monitor() { delete _impl; }
Marc Slemko66949872006-07-15 01:52:39 +000094
Mark Sleef5f2be42006-09-05 21:05:31 +000095void Monitor::lock() const { _impl->lock(); }
Marc Slemko66949872006-07-15 01:52:39 +000096
Mark Sleef5f2be42006-09-05 21:05:31 +000097void Monitor::unlock() const { _impl->unlock(); }
Marc Slemko66949872006-07-15 01:52:39 +000098
Mark Sleef5f2be42006-09-05 21:05:31 +000099void Monitor::wait(long long timeout) const { _impl->wait(timeout); }
Marc Slemko66949872006-07-15 01:52:39 +0000100
Mark Sleef5f2be42006-09-05 21:05:31 +0000101void Monitor::notify() const { _impl->notify(); }
Marc Slemko66949872006-07-15 01:52:39 +0000102
Mark Sleef5f2be42006-09-05 21:05:31 +0000103void Monitor::notifyAll() const { _impl->notifyAll(); }
Marc Slemko66949872006-07-15 01:52:39 +0000104
105}}} // facebook::thrift::concurrency