blob: b1d7b726ac2e5f1e58677c78ac977ed2b049a089 [file] [log] [blame]
#include "Monitor.h"
#include "Exception.h"
#include "Util.h"
#include <assert.h>
#include <errno.h>
#include <iostream>
#include <pthread.h>
namespace facebook { namespace thrift { namespace concurrency {
/** Monitor implementation using the POSIX pthread library
@author marc
@version $Id:$ */
class Monitor::Impl {
public:
Impl() :
mutexInitialized(false) {
/* XXX
Need to fix this to handle failures without leaking. */
assert(pthread_mutex_init(&_pthread_mutex, NULL) == 0);
mutexInitialized = true;
assert(pthread_cond_init(&_pthread_cond, NULL) == 0);
}
~Impl() {
if(mutexInitialized) {
mutexInitialized = false;
assert(pthread_mutex_destroy(&_pthread_mutex) == 0);
}
if(condInitialized) {
condInitialized = false;
assert(pthread_cond_destroy(&_pthread_cond) == 0);
}
}
void lock() const {pthread_mutex_lock(&_pthread_mutex);}
void unlock() const {pthread_mutex_unlock(&_pthread_mutex);}
void wait(long long timeout) const {
// XXX Need to assert that caller owns mutex
assert(timeout >= 0LL);
if(timeout == 0LL) {
assert(pthread_cond_wait(&_pthread_cond, &_pthread_mutex) == 0);
} else {
struct timespec abstime;
long long now = Util::currentTime();
Util::toTimespec(abstime, now + timeout);
int result = pthread_cond_timedwait(&_pthread_cond, &_pthread_mutex, &abstime);
if(result == ETIMEDOUT) {
assert(Util::currentTime() >= (now + timeout));
}
}
}
void notify() {
// XXX Need to assert that caller owns mutex
assert(pthread_cond_signal(&_pthread_cond) == 0);
}
void notifyAll() {
// XXX Need to assert that caller owns mutex
assert(pthread_cond_broadcast(&_pthread_cond) == 0);
}
private:
mutable pthread_mutex_t _pthread_mutex;
mutable bool mutexInitialized;
mutable pthread_cond_t _pthread_cond;
mutable bool condInitialized;
};
Monitor::Monitor() : _impl(new Monitor::Impl()) {}
Monitor::~Monitor() { delete _impl;}
void Monitor::lock() const {_impl->lock();}
void Monitor::unlock() const {_impl->unlock();}
void Monitor::wait(long long timeout) const {_impl->wait(timeout);}
void Monitor::notify() const {_impl->notify();}
void Monitor::notifyAll() const {_impl->notifyAll();}
}}} // facebook::thrift::concurrency