Ack. Thanks, Ramesh.
On 11/8/2016 8:50 PM, Anders Widell wrote: > 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_ ------------------------------------------------------------------------------ _______________________________________________ Opensaf-devel mailing list Opensaf-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/opensaf-devel