Checkpoint of initial cut at thread pool manager for thrift and related concurrency classes.
git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@664721 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/lib/cpp/src/concurrency/Monitor.cc b/lib/cpp/src/concurrency/Monitor.cc
new file mode 100644
index 0000000..d1b83d1
--- /dev/null
+++ b/lib/cpp/src/concurrency/Monitor.cc
@@ -0,0 +1,138 @@
+#include "Monitor.h"
+
+#include <assert.h>
+#include <errno.h>
+#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
+
+ if(timeout == 0LL) {
+
+ pthread_cond_wait(&_pthread_cond, &_pthread_mutex);
+
+ } else {
+
+ struct timespec abstime;
+
+ toAbsoluteTimespec(abstime, timeout);
+
+ int result = pthread_cond_timedwait(&_pthread_cond, &_pthread_mutex, &abstime);
+
+ if(result == ETIMEDOUT) {
+
+ // XXX If result is timeout need to throw timeout exception
+ }
+ }
+ }
+
+ 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:
+
+ /** Converts relative timeout specified as a duration in milliseconds to a struct timespec structure
+ specifying current time plus timeout
+
+ @param timeout time to delay in milliseconds
+ @return struct timespec current time plus timeout */
+
+ static const void toAbsoluteTimespec(struct timespec& result, long long timeout) {
+
+ // XXX Darwin doesn't seem to have any readily useable hi-res clock.
+
+ time_t seconds;
+
+ assert(time(&seconds) != (time_t)-1);
+
+ seconds+= (timeout / 1000);
+
+ long nanoseconds = (timeout % 1000) * 1000000;
+
+ result.tv_sec = seconds + (nanoseconds / 1000000000);
+
+ result.tv_nsec = nanoseconds % 1000000000;
+ }
+
+ 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
+