summaryrefslogtreecommitdiff
path: root/lib/cpp/src/concurrency/Monitor.cpp
diff options
context:
space:
mode:
authorGavin McDonald <gmcdonald@apache.org>2010-10-28 02:12:01 +0000
committerGavin McDonald <gmcdonald@apache.org>2010-10-28 02:12:01 +0000
commit0b75e1ac7643787e201fd62628823e6d51ca6353 (patch)
tree4417fd3f2bc201f0f34c2344f0923df1485bc419 /lib/cpp/src/concurrency/Monitor.cpp
downloadthrift-0.1.x.tar.gz
Thrift now a TLP - INFRA-31160.1.x
git-svn-id: https://svn.apache.org/repos/asf/thrift/branches/0.1.x@1028168 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'lib/cpp/src/concurrency/Monitor.cpp')
-rw-r--r--lib/cpp/src/concurrency/Monitor.cpp137
1 files changed, 137 insertions, 0 deletions
diff --git a/lib/cpp/src/concurrency/Monitor.cpp b/lib/cpp/src/concurrency/Monitor.cpp
new file mode 100644
index 000000000..2055caa95
--- /dev/null
+++ b/lib/cpp/src/concurrency/Monitor.cpp
@@ -0,0 +1,137 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include "Monitor.h"
+#include "Exception.h"
+#include "Util.h"
+
+#include <assert.h>
+#include <errno.h>
+
+#include <iostream>
+
+#include <pthread.h>
+
+namespace apache { namespace thrift { namespace concurrency {
+
+/**
+ * Monitor implementation using the POSIX pthread library
+ *
+ * @version $Id:$
+ */
+class Monitor::Impl {
+
+ public:
+
+ Impl() :
+ mutexInitialized_(false),
+ condInitialized_(false) {
+
+ if (pthread_mutex_init(&pthread_mutex_, NULL) == 0) {
+ mutexInitialized_ = true;
+
+ if (pthread_cond_init(&pthread_cond_, NULL) == 0) {
+ condInitialized_ = true;
+ }
+ }
+
+ if (!mutexInitialized_ || !condInitialized_) {
+ cleanup();
+ throw SystemResourceException();
+ }
+ }
+
+ ~Impl() { cleanup(); }
+
+ void lock() const { pthread_mutex_lock(&pthread_mutex_); }
+
+ void unlock() const { pthread_mutex_unlock(&pthread_mutex_); }
+
+ void wait(int64_t timeout) const {
+
+ // XXX Need to assert that caller owns mutex
+ assert(timeout >= 0LL);
+ if (timeout == 0LL) {
+ int iret = pthread_cond_wait(&pthread_cond_, &pthread_mutex_);
+ assert(iret == 0);
+ } else {
+ struct timespec abstime;
+ int64_t now = Util::currentTime();
+ Util::toTimespec(abstime, now + timeout);
+ int result = pthread_cond_timedwait(&pthread_cond_,
+ &pthread_mutex_,
+ &abstime);
+ if (result == ETIMEDOUT) {
+ // pthread_cond_timedwait has been observed to return early on
+ // various platforms, so comment out this assert.
+ //assert(Util::currentTime() >= (now + timeout));
+ throw TimedOutException();
+ }
+ }
+ }
+
+ void notify() {
+ // XXX Need to assert that caller owns mutex
+ int iret = pthread_cond_signal(&pthread_cond_);
+ assert(iret == 0);
+ }
+
+ void notifyAll() {
+ // XXX Need to assert that caller owns mutex
+ int iret = pthread_cond_broadcast(&pthread_cond_);
+ assert(iret == 0);
+ }
+
+ private:
+
+ void cleanup() {
+ if (mutexInitialized_) {
+ mutexInitialized_ = false;
+ int iret = pthread_mutex_destroy(&pthread_mutex_);
+ assert(iret == 0);
+ }
+
+ if (condInitialized_) {
+ condInitialized_ = false;
+ int iret = pthread_cond_destroy(&pthread_cond_);
+ assert(iret == 0);
+ }
+ }
+
+ 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(int64_t timeout) const { impl_->wait(timeout); }
+
+void Monitor::notify() const { impl_->notify(); }
+
+void Monitor::notifyAll() const { impl_->notifyAll(); }
+
+}}} // apache::thrift::concurrency