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
+