osaf/libs/core/cplusplus/base/Makefile.am           |   4 +
 osaf/libs/core/cplusplus/base/condition_variable.cc |  39 ++++++++
 osaf/libs/core/cplusplus/base/condition_variable.h  |  95 +++++++++++++++++++++
 osaf/libs/core/cplusplus/base/mutex.cc              |  46 ++++++++++
 osaf/libs/core/cplusplus/base/mutex.h               |  82 ++++++++++++++++++
 5 files changed, 266 insertions(+), 0 deletions(-)


Add classes for Mutex, Lock and ConditionVariable - similar to std::mutex,
std::unique_lock and std::condition_variable. One reason for adding these to
OpenSAF is that the C++ standard library casses are unapproved by the Google C++
Style Guide. Another reason is that we can integrate them better into OpenSAF:
we select the appropriate options when creating the mutex and condition
variable, and we call osaf_abort() in case an unexpected error is
encountered. Also, we will use an error checking mutex when the ENABLE_DEBUG
preprocessor macro is defined - paving the way for special OpenSAF debug builds.

diff --git a/osaf/libs/core/cplusplus/base/Makefile.am 
b/osaf/libs/core/cplusplus/base/Makefile.am
--- a/osaf/libs/core/cplusplus/base/Makefile.am
+++ b/osaf/libs/core/cplusplus/base/Makefile.am
@@ -28,6 +28,8 @@ noinst_HEADERS = \
        getenv.h \
        log_message.h \
        macros.h \
+       mutex.h \
+       condition_variable.h \
        process.h \
        time.h \
        unix_client_socket.h \
@@ -48,6 +50,8 @@ libbase_la_SOURCES = \
        getenv.cc \
        log_message.cc \
        process.cc \
+       mutex.cc \
+       condition_variable.cc \
        unix_client_socket.cc \
        unix_server_socket.cc \
        unix_socket.cc
diff --git a/osaf/libs/core/cplusplus/base/condition_variable.cc 
b/osaf/libs/core/cplusplus/base/condition_variable.cc
new file mode 100644
--- /dev/null
+++ b/osaf/libs/core/cplusplus/base/condition_variable.cc
@@ -0,0 +1,39 @@
+/*      -*- OpenSAF  -*-
+ *
+ * (C) Copyright 2016 The OpenSAF Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed
+ * under the GNU Lesser General Public License Version 2.1, February 1999.
+ * The complete license can be accessed from the following location:
+ * http://opensource.org/licenses/lgpl-license.php
+ * See the Copying file included with the OpenSAF distribution for full
+ * licensing terms.
+ *
+ * Author(s): Ericsson AB
+ *
+ */
+
+#include "osaf/libs/core/cplusplus/base/condition_variable.h"
+
+namespace base {
+
+ConditionVariable::ConditionVariable() : condition_variable_{} {
+  pthread_condattr_t attr;
+  int result = pthread_condattr_init(&attr);
+  if (result != 0) osaf_abort(result);
+  result = pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
+  if (result != 0) osaf_abort(result);
+  result = pthread_cond_init(&condition_variable_, &attr);
+  if (result != 0) osaf_abort(result);
+  result = pthread_condattr_destroy(&attr);
+  if (result != 0) osaf_abort(result);
+}
+
+ConditionVariable::~ConditionVariable() {
+  int result = pthread_cond_destroy(&condition_variable_);
+  if (result != 0) osaf_abort(result);
+}
+
+}  // namespace base
diff --git a/osaf/libs/core/cplusplus/base/condition_variable.h 
b/osaf/libs/core/cplusplus/base/condition_variable.h
new file mode 100644
--- /dev/null
+++ b/osaf/libs/core/cplusplus/base/condition_variable.h
@@ -0,0 +1,95 @@
+/*      -*- OpenSAF  -*-
+ *
+ * (C) Copyright 2016 The OpenSAF Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed
+ * under the GNU Lesser General Public License Version 2.1, February 1999.
+ * The complete license can be accessed from the following location:
+ * http://opensource.org/licenses/lgpl-license.php
+ * See the Copying file included with the OpenSAF distribution for full
+ * licensing terms.
+ *
+ * Author(s): Ericsson AB
+ *
+ */
+
+#ifndef OSAF_LIBS_CORE_CPLUSPLUS_BASE_CONDITION_VARIABLE_H_
+#define OSAF_LIBS_CORE_CPLUSPLUS_BASE_CONDITION_VARIABLE_H_
+
+#include <pthread.h>
+#include <cerrno>
+#include "osaf/libs/core/common/include/osaf_utility.h"
+#include "osaf/libs/core/cplusplus/base/macros.h"
+#include "osaf/libs/core/cplusplus/base/mutex.h"
+#include "osaf/libs/core/cplusplus/base/time.h"
+
+namespace base {
+
+enum class CvStatus { kNoTimeout, kTimeout };
+
+// A condition variable, with an API similar to std::condition_variable. The
+// timed methods always use the monotonic clock (clock id CLOCK_MONOTONIC).
+class ConditionVariable {
+ public:
+  ConditionVariable();
+  ~ConditionVariable();
+  void Wait(Lock* lock) {
+    int result = pthread_cond_wait(&condition_variable_,
+                                   lock->mutex()->native_handle());
+    if (result != 0) osaf_abort(result);
+  }
+  template <typename Predicate>
+  void Wait(Lock* lock, Predicate predicate) {
+    while (!predicate()) Wait(lock);
+  }
+  CvStatus WaitUntil(Lock* lock, const struct timespec& absolute_time) {
+    int result = pthread_cond_timedwait(&condition_variable_,
+                                        lock->mutex()->native_handle(),
+                                        &absolute_time);
+    if (result == 0) {
+      return CvStatus::kNoTimeout;
+    } else if (result == ETIMEDOUT) {
+      return CvStatus::kTimeout;
+    } else {
+      osaf_abort(result);
+    }
+  }
+  template <typename Predicate>
+  bool WaitUntil(Lock* lock, const struct timespec& absolute_time,
+                 Predicate predicate) {
+    while (!predicate()) {
+      if (WaitUntil(lock, absolute_time) == CvStatus::kTimeout) {
+        return predicate();
+      }
+    }
+    return true;
+  }
+  CvStatus WaitFor(Lock* lock, const struct timespec& relative_time) {
+    struct timespec absolute_time = base::ReadMonotonicClock() + relative_time;
+    return WaitUntil(lock, absolute_time);
+  }
+  template <typename Predicate>
+  bool WaitFor(Lock* lock, const struct timespec& relative_time,
+               Predicate predicate) {
+    struct timespec absolute_time = base::ReadMonotonicClock() + relative_time;
+    return WaitUntil(lock, absolute_time, predicate);
+  }
+  void NotifyOne() {
+    int result = pthread_cond_signal(&condition_variable_);
+    if (result != 0) osaf_abort(result);
+  }
+  void NotifyAll() {
+    int result = pthread_cond_broadcast(&condition_variable_);
+    if (result != 0) osaf_abort(result);
+  }
+
+ private:
+  pthread_cond_t condition_variable_;
+  DELETE_COPY_AND_MOVE_OPERATORS(ConditionVariable);
+};
+
+}  // namespace base
+
+#endif  // OSAF_LIBS_CORE_CPLUSPLUS_BASE_CONDITION_VARIABLE_H_
diff --git a/osaf/libs/core/cplusplus/base/mutex.cc 
b/osaf/libs/core/cplusplus/base/mutex.cc
new file mode 100644
--- /dev/null
+++ b/osaf/libs/core/cplusplus/base/mutex.cc
@@ -0,0 +1,46 @@
+/*      -*- OpenSAF  -*-
+ *
+ * (C) Copyright 2016 The OpenSAF Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed
+ * under the GNU Lesser General Public License Version 2.1, February 1999.
+ * The complete license can be accessed from the following location:
+ * http://opensource.org/licenses/lgpl-license.php
+ * See the Copying file included with the OpenSAF distribution for full
+ * licensing terms.
+ *
+ * Author(s): Ericsson AB
+ *
+ */
+
+#include "osaf/libs/core/cplusplus/base/mutex.h"
+#include "./config.h"
+
+namespace base {
+
+Mutex::Mutex() : mutex_{} {
+  pthread_mutexattr_t attr;
+  int result = pthread_mutexattr_init(&attr);
+  if (result != 0) osaf_abort(result);
+  result = pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT);
+  if (result != 0) osaf_abort(result);
+#ifdef ENABLE_DEBUG
+  result = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
+  if (result != 0) osaf_abort(result);
+  result = pthread_mutexattr_setrobust(&attr, PTHREAD_MUTEX_ROBUST);
+  if (result != 0) osaf_abort(result);
+#endif
+  result = pthread_mutex_init(&mutex_, &attr);
+  if (result != 0) osaf_abort(result);
+  result = pthread_mutexattr_destroy(&attr);
+  if (result != 0) osaf_abort(result);
+}
+
+Mutex::~Mutex() {
+  int result = pthread_mutex_destroy(&mutex_);
+  if (result != 0) osaf_abort(result);
+}
+
+}  // namespace base
diff --git a/osaf/libs/core/cplusplus/base/mutex.h 
b/osaf/libs/core/cplusplus/base/mutex.h
new file mode 100644
--- /dev/null
+++ b/osaf/libs/core/cplusplus/base/mutex.h
@@ -0,0 +1,82 @@
+/*      -*- OpenSAF  -*-
+ *
+ * (C) Copyright 2016 The OpenSAF Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed
+ * under the GNU Lesser General Public License Version 2.1, February 1999.
+ * The complete license can be accessed from the following location:
+ * http://opensource.org/licenses/lgpl-license.php
+ * See the Copying file included with the OpenSAF distribution for full
+ * licensing terms.
+ *
+ * Author(s): Ericsson AB
+ *
+ */
+
+#ifndef OSAF_LIBS_CORE_CPLUSPLUS_BASE_MUTEX_H_
+#define OSAF_LIBS_CORE_CPLUSPLUS_BASE_MUTEX_H_
+
+#include <pthread.h>
+#include <cerrno>
+#include "osaf/libs/core/common/include/osaf_utility.h"
+#include "osaf/libs/core/cplusplus/base/macros.h"
+
+namespace base {
+
+// A mutex, with an API compatible with std::mutex. When built with the
+// preprocessor macro ENABLE_DEBUG defined, the mutex will be created with 
error
+// checking enabled.
+class Mutex {
+ public:
+  using NativeHandleType = pthread_mutex_t*;
+  Mutex();
+  ~Mutex();
+  void Lock() {
+    int result = pthread_mutex_lock(&mutex_);
+    if (result != 0) osaf_abort(result);
+  }
+  bool TryLock() {
+    int result = pthread_mutex_trylock(&mutex_);
+    if (result == 0) {
+      return true;
+    } else if (result == EBUSY) {
+      return false;
+    } else {
+      osaf_abort(result);
+    }
+  }
+  void Unlock() {
+    int result = pthread_mutex_unlock(&mutex_);
+    if (result != 0) osaf_abort(result);
+  }
+  NativeHandleType native_handle() { return &mutex_; }
+
+ private:
+  pthread_mutex_t mutex_;
+  DELETE_COPY_AND_MOVE_OPERATORS(Mutex);
+};
+
+// A lock manager, with an API similar to std::unique_lock, but simplified so
+// that the mutex is always held during the lifetime of the lock object - i.e.
+// this class enforces the RAAI idiom.
+class Lock {
+ public:
+  explicit Lock(Mutex& mutex) : mutex_{&mutex} { mutex_->Lock(); }
+  ~Lock() { mutex_->Unlock(); }
+  void Swap(Lock& lock) {
+    Mutex* tmp = mutex_;
+    mutex_ = lock.mutex_;
+    lock.mutex_ = tmp;
+  }
+  Mutex* mutex() const { return mutex_; }
+
+ private:
+  Mutex* mutex_;
+  DELETE_COPY_AND_MOVE_OPERATORS(Lock);
+};
+
+}  // namespace base
+
+#endif  // OSAF_LIBS_CORE_CPLUSPLUS_BASE_MUTEX_H_

------------------------------------------------------------------------------
Developer Access Program for Intel Xeon Phi Processors
Access to Intel Xeon Phi processor-based developer platforms.
With one year of Intel Parallel Studio XE.
Training and support from Colfax.
Order your platform today. http://sdm.link/xeonphi
_______________________________________________
Opensaf-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/opensaf-devel

Reply via email to