blob: ecd82ade33197b711d02b45f26cb6ba0e4808b3b [file] [log] [blame]
Mark Slee9f0c6512007-02-28 23:58:26 +00001// Copyright (c) 2006- Facebook
2// Distributed under the Thrift Software License
3//
4// See accompanying file LICENSE or visit the Thrift site at:
5// http://developers.facebook.com/thrift/
6
Marc Slemko66949872006-07-15 01:52:39 +00007#include "Monitor.h"
Marc Slemko8a40a762006-07-19 17:46:50 +00008#include "Exception.h"
Marc Slemko0e53ccd2006-07-17 23:51:05 +00009#include "Util.h"
Marc Slemko66949872006-07-15 01:52:39 +000010
11#include <assert.h>
12#include <errno.h>
Marc Slemko8a40a762006-07-19 17:46:50 +000013
14#include <iostream>
15
Marc Slemko66949872006-07-15 01:52:39 +000016#include <pthread.h>
17
18namespace facebook { namespace thrift { namespace concurrency {
19
Mark Sleef5f2be42006-09-05 21:05:31 +000020/**
21 * Monitor implementation using the POSIX pthread library
22 *
23 * @author marc
24 * @version $Id:$
25 */
Marc Slemko66949872006-07-15 01:52:39 +000026class Monitor::Impl {
27
28 public:
29
Mark Sleef5f2be42006-09-05 21:05:31 +000030 Impl() :
Mark Slee2f6404d2006-10-10 01:37:40 +000031 mutexInitialized_(false),
32 condInitialized_(false) {
Marc Slemko66949872006-07-15 01:52:39 +000033
Marc Slemko6f038a72006-08-03 18:58:09 +000034 try {
Mark Slee2f6404d2006-10-10 01:37:40 +000035 assert(pthread_mutex_init(&pthread_mutex_, NULL) == 0);
36 mutexInitialized_ = true;
37 assert(pthread_cond_init(&pthread_cond_, NULL) == 0);
38 condInitialized_ = true;
Marc Slemko6f038a72006-08-03 18:58:09 +000039 } catch(...) {
40 cleanup();
Marc Slemko66949872006-07-15 01:52:39 +000041 }
42 }
43
Mark Sleef5f2be42006-09-05 21:05:31 +000044 ~Impl() { cleanup(); }
Marc Slemko6f038a72006-08-03 18:58:09 +000045
Mark Slee2f6404d2006-10-10 01:37:40 +000046 void lock() const { pthread_mutex_lock(&pthread_mutex_); }
Marc Slemko66949872006-07-15 01:52:39 +000047
Mark Slee2f6404d2006-10-10 01:37:40 +000048 void unlock() const { pthread_mutex_unlock(&pthread_mutex_); }
Marc Slemko66949872006-07-15 01:52:39 +000049
50 void wait(long long timeout) const {
51
52 // XXX Need to assert that caller owns mutex
Marc Slemko9f27a4e2006-07-19 20:02:22 +000053 assert(timeout >= 0LL);
Mark Sleef5f2be42006-09-05 21:05:31 +000054 if (timeout == 0LL) {
Mark Slee2f6404d2006-10-10 01:37:40 +000055 assert(pthread_cond_wait(&pthread_cond_, &pthread_mutex_) == 0);
Marc Slemko66949872006-07-15 01:52:39 +000056 } else {
Marc Slemko66949872006-07-15 01:52:39 +000057 struct timespec abstime;
Marc Slemko9f27a4e2006-07-19 20:02:22 +000058 long long now = Util::currentTime();
Marc Slemko9f27a4e2006-07-19 20:02:22 +000059 Util::toTimespec(abstime, now + timeout);
Mark Slee2f6404d2006-10-10 01:37:40 +000060 int result = pthread_cond_timedwait(&pthread_cond_,
61 &pthread_mutex_,
62 &abstime);
Mark Sleef5f2be42006-09-05 21:05:31 +000063 if (result == ETIMEDOUT) {
Marc Slemko9f27a4e2006-07-19 20:02:22 +000064 assert(Util::currentTime() >= (now + timeout));
Marc Slemko66949872006-07-15 01:52:39 +000065 }
66 }
67 }
68
69 void notify() {
Marc Slemko66949872006-07-15 01:52:39 +000070 // XXX Need to assert that caller owns mutex
Mark Slee2f6404d2006-10-10 01:37:40 +000071 assert(pthread_cond_signal(&pthread_cond_) == 0);
Marc Slemko66949872006-07-15 01:52:39 +000072 }
73
74 void notifyAll() {
Marc Slemko66949872006-07-15 01:52:39 +000075 // XXX Need to assert that caller owns mutex
Mark Slee2f6404d2006-10-10 01:37:40 +000076 assert(pthread_cond_broadcast(&pthread_cond_) == 0);
Marc Slemko66949872006-07-15 01:52:39 +000077 }
78
Mark Sleef5f2be42006-09-05 21:05:31 +000079 private:
Marc Slemko66949872006-07-15 01:52:39 +000080
Marc Slemko6f038a72006-08-03 18:58:09 +000081 void cleanup() {
Mark Slee2f6404d2006-10-10 01:37:40 +000082 if (mutexInitialized_) {
83 mutexInitialized_ = false;
84 assert(pthread_mutex_destroy(&pthread_mutex_) == 0);
Marc Slemko6f038a72006-08-03 18:58:09 +000085 }
86
Mark Slee2f6404d2006-10-10 01:37:40 +000087 if (condInitialized_) {
88 condInitialized_ = false;
89 assert(pthread_cond_destroy(&pthread_cond_) == 0);
Marc Slemko6f038a72006-08-03 18:58:09 +000090 }
91 }
92
Mark Slee2f6404d2006-10-10 01:37:40 +000093 mutable pthread_mutex_t pthread_mutex_;
94 mutable bool mutexInitialized_;
95 mutable pthread_cond_t pthread_cond_;
96 mutable bool condInitialized_;
Marc Slemko66949872006-07-15 01:52:39 +000097};
98
Mark Slee2f6404d2006-10-10 01:37:40 +000099Monitor::Monitor() : impl_(new Monitor::Impl()) {}
Marc Slemko66949872006-07-15 01:52:39 +0000100
Mark Slee2f6404d2006-10-10 01:37:40 +0000101Monitor::~Monitor() { delete impl_; }
Marc Slemko66949872006-07-15 01:52:39 +0000102
Mark Slee2f6404d2006-10-10 01:37:40 +0000103void Monitor::lock() const { impl_->lock(); }
Marc Slemko66949872006-07-15 01:52:39 +0000104
Mark Slee2f6404d2006-10-10 01:37:40 +0000105void Monitor::unlock() const { impl_->unlock(); }
Marc Slemko66949872006-07-15 01:52:39 +0000106
Mark Slee2f6404d2006-10-10 01:37:40 +0000107void Monitor::wait(long long timeout) const { impl_->wait(timeout); }
Marc Slemko66949872006-07-15 01:52:39 +0000108
Mark Slee2f6404d2006-10-10 01:37:40 +0000109void Monitor::notify() const { impl_->notify(); }
Marc Slemko66949872006-07-15 01:52:39 +0000110
Mark Slee2f6404d2006-10-10 01:37:40 +0000111void Monitor::notifyAll() const { impl_->notifyAll(); }
Marc Slemko66949872006-07-15 01:52:39 +0000112
113}}} // facebook::thrift::concurrency