blob: 2443a6eb71583c67599f1a51f06f5072275609f3 [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 {
Aditya Agarwal9dc57402007-03-31 17:45:12 +000035 int ret = pthread_mutex_init(&pthread_mutex_, NULL);
Aditya Agarwal3f234da2007-04-01 01:19:57 +000036 assert(ret == 0);
Mark Slee2f6404d2006-10-10 01:37:40 +000037 mutexInitialized_ = true;
Aditya Agarwal9dc57402007-03-31 17:45:12 +000038 ret = pthread_cond_init(&pthread_cond_, NULL);
Aditya Agarwal3f234da2007-04-01 01:19:57 +000039 assert(ret == 0);
Mark Slee2f6404d2006-10-10 01:37:40 +000040 condInitialized_ = true;
Marc Slemko6f038a72006-08-03 18:58:09 +000041 } catch(...) {
42 cleanup();
Marc Slemko66949872006-07-15 01:52:39 +000043 }
44 }
45
Mark Sleef5f2be42006-09-05 21:05:31 +000046 ~Impl() { cleanup(); }
Marc Slemko6f038a72006-08-03 18:58:09 +000047
Mark Slee2f6404d2006-10-10 01:37:40 +000048 void lock() const { pthread_mutex_lock(&pthread_mutex_); }
Marc Slemko66949872006-07-15 01:52:39 +000049
Mark Slee2f6404d2006-10-10 01:37:40 +000050 void unlock() const { pthread_mutex_unlock(&pthread_mutex_); }
Marc Slemko66949872006-07-15 01:52:39 +000051
52 void wait(long long timeout) const {
53
54 // XXX Need to assert that caller owns mutex
Aditya Agarwal3f234da2007-04-01 01:19:57 +000055 assert(timeout >= 0LL);
Mark Sleef5f2be42006-09-05 21:05:31 +000056 if (timeout == 0LL) {
Aditya Agarwal9dc57402007-03-31 17:45:12 +000057 int iret = pthread_cond_wait(&pthread_cond_, &pthread_mutex_);
Aditya Agarwal3f234da2007-04-01 01:19:57 +000058 assert(iret == 0);
Marc Slemko66949872006-07-15 01:52:39 +000059 } else {
Marc Slemko66949872006-07-15 01:52:39 +000060 struct timespec abstime;
Marc Slemko9f27a4e2006-07-19 20:02:22 +000061 long long now = Util::currentTime();
Marc Slemko9f27a4e2006-07-19 20:02:22 +000062 Util::toTimespec(abstime, now + timeout);
Mark Slee2f6404d2006-10-10 01:37:40 +000063 int result = pthread_cond_timedwait(&pthread_cond_,
64 &pthread_mutex_,
65 &abstime);
Mark Sleef5f2be42006-09-05 21:05:31 +000066 if (result == ETIMEDOUT) {
Aditya Agarwal3f234da2007-04-01 01:19:57 +000067 assert(Util::currentTime() >= (now + timeout));
Marc Slemko66949872006-07-15 01:52:39 +000068 }
69 }
70 }
71
72 void notify() {
Marc Slemko66949872006-07-15 01:52:39 +000073 // XXX Need to assert that caller owns mutex
Aditya Agarwal9dc57402007-03-31 17:45:12 +000074 int iret = pthread_cond_signal(&pthread_cond_);
Aditya Agarwal3f234da2007-04-01 01:19:57 +000075 assert(iret == 0);
Marc Slemko66949872006-07-15 01:52:39 +000076 }
77
78 void notifyAll() {
Marc Slemko66949872006-07-15 01:52:39 +000079 // XXX Need to assert that caller owns mutex
Aditya Agarwal9dc57402007-03-31 17:45:12 +000080 int iret = pthread_cond_broadcast(&pthread_cond_);
Aditya Agarwal3f234da2007-04-01 01:19:57 +000081 assert(iret == 0);
Marc Slemko66949872006-07-15 01:52:39 +000082 }
83
Mark Sleef5f2be42006-09-05 21:05:31 +000084 private:
Marc Slemko66949872006-07-15 01:52:39 +000085
Marc Slemko6f038a72006-08-03 18:58:09 +000086 void cleanup() {
Mark Slee2f6404d2006-10-10 01:37:40 +000087 if (mutexInitialized_) {
88 mutexInitialized_ = false;
Aditya Agarwal9dc57402007-03-31 17:45:12 +000089 int iret = pthread_mutex_destroy(&pthread_mutex_);
Aditya Agarwal3f234da2007-04-01 01:19:57 +000090 assert(iret == 0);
Marc Slemko6f038a72006-08-03 18:58:09 +000091 }
92
Mark Slee2f6404d2006-10-10 01:37:40 +000093 if (condInitialized_) {
94 condInitialized_ = false;
Aditya Agarwal9dc57402007-03-31 17:45:12 +000095 int iret = pthread_cond_destroy(&pthread_cond_);
Aditya Agarwal3f234da2007-04-01 01:19:57 +000096 assert(iret == 0);
Marc Slemko6f038a72006-08-03 18:58:09 +000097 }
98 }
99
Mark Slee2f6404d2006-10-10 01:37:40 +0000100 mutable pthread_mutex_t pthread_mutex_;
101 mutable bool mutexInitialized_;
102 mutable pthread_cond_t pthread_cond_;
103 mutable bool condInitialized_;
Marc Slemko66949872006-07-15 01:52:39 +0000104};
105
Mark Slee2f6404d2006-10-10 01:37:40 +0000106Monitor::Monitor() : impl_(new Monitor::Impl()) {}
Marc Slemko66949872006-07-15 01:52:39 +0000107
Mark Slee2f6404d2006-10-10 01:37:40 +0000108Monitor::~Monitor() { delete impl_; }
Marc Slemko66949872006-07-15 01:52:39 +0000109
Mark Slee2f6404d2006-10-10 01:37:40 +0000110void Monitor::lock() const { impl_->lock(); }
Marc Slemko66949872006-07-15 01:52:39 +0000111
Mark Slee2f6404d2006-10-10 01:37:40 +0000112void Monitor::unlock() const { impl_->unlock(); }
Marc Slemko66949872006-07-15 01:52:39 +0000113
Mark Slee2f6404d2006-10-10 01:37:40 +0000114void Monitor::wait(long long timeout) const { impl_->wait(timeout); }
Marc Slemko66949872006-07-15 01:52:39 +0000115
Mark Slee2f6404d2006-10-10 01:37:40 +0000116void Monitor::notify() const { impl_->notify(); }
Marc Slemko66949872006-07-15 01:52:39 +0000117
Mark Slee2f6404d2006-10-10 01:37:40 +0000118void Monitor::notifyAll() const { impl_->notifyAll(); }
Marc Slemko66949872006-07-15 01:52:39 +0000119
120}}} // facebook::thrift::concurrency