From c6dab613003c704f072542f39214f7af64fc0412 Mon Sep 17 00:00:00 2001 From: David Reiss Date: Tue, 10 Jun 2008 22:55:13 +0000 Subject: [PATCH] Thrift: Allow for alternative Mutex initializers. Summary: Add an argument to the Mutex constructor. It takes a pointer to a function that initializes the internal pthread_mutex_t. We provide initializers for default pthread_mutex_t (which is our default), adaptive mutexes, and recursive mutexes. Reviewed By: hzhao, psaab, mcslee Test Plan: Built libthrift. git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@666362 13f79535-47bb-0310-9956-ffa450edef68 --- lib/cpp/src/concurrency/Mutex.cpp | 50 ++++++++++++++++++++++++++++--- lib/cpp/src/concurrency/Mutex.h | 12 +++++++- 2 files changed, 57 insertions(+), 5 deletions(-) diff --git a/lib/cpp/src/concurrency/Mutex.cpp b/lib/cpp/src/concurrency/Mutex.cpp index 87bfd354..b160b670 100644 --- a/lib/cpp/src/concurrency/Mutex.cpp +++ b/lib/cpp/src/concurrency/Mutex.cpp @@ -21,9 +21,8 @@ namespace facebook { namespace thrift { namespace concurrency { */ class Mutex::impl { public: - impl() : initialized_(false) { - int ret = pthread_mutex_init(&pthread_mutex_, NULL); - assert(ret == 0); + impl(Initializer init) : initialized_(false) { + init(&pthread_mutex_); initialized_ = true; } @@ -46,7 +45,7 @@ class Mutex::impl { mutable bool initialized_; }; -Mutex::Mutex() : impl_(new Mutex::impl()) {} +Mutex::Mutex(Initializer init) : impl_(new Mutex::impl(init)) {} void Mutex::lock() const { impl_->lock(); } @@ -54,6 +53,49 @@ bool Mutex::trylock() const { return impl_->trylock(); } void Mutex::unlock() const { impl_->unlock(); } +void Mutex::DEFAULT_INITIALIZER(void* arg) { + pthread_mutex_t* pthread_mutex = (pthread_mutex_t*)arg; + int ret = pthread_mutex_init(pthread_mutex, NULL); + assert(ret == 0); +} + +static void init_with_kind(pthread_mutex_t* mutex, int kind) { + pthread_mutexattr_t mutexattr; + int ret = pthread_mutexattr_init(&mutexattr); + assert(ret == 0); + + // Apparently, this can fail. Should we really be aborting? + ret = pthread_mutexattr_settype(&mutexattr, kind); + assert(ret == 0); + + ret = pthread_mutex_init(mutex, &mutexattr); + assert(ret == 0); + + ret = pthread_mutexattr_destroy(&mutexattr); + assert(ret == 0); +} + +#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP +void Mutex::ADAPTIVE_INITIALIZER(void* arg) { + // From mysql source: mysys/my_thr_init.c + // Set mutex type to "fast" a.k.a "adaptive" + // + // In this case the thread may steal the mutex from some other thread + // that is waiting for the same mutex. This will save us some + // context switches but may cause a thread to 'starve forever' while + // waiting for the mutex (not likely if the code within the mutex is + // short). + init_with_kind((pthread_mutex_t*)arg, PTHREAD_MUTEX_ADAPTIVE_NP); +} +#endif + +#ifdef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP +void Mutex::RECURSIVE_INITIALIZER(void* arg) { + init_with_kind((pthread_mutex_t*)arg, PTHREAD_MUTEX_RECURSIVE_NP); +} +#endif + + /** * Implementation of ReadWriteMutex class using POSIX rw lock * diff --git a/lib/cpp/src/concurrency/Mutex.h b/lib/cpp/src/concurrency/Mutex.h index e176628a..7830d686 100644 --- a/lib/cpp/src/concurrency/Mutex.h +++ b/lib/cpp/src/concurrency/Mutex.h @@ -19,12 +19,22 @@ namespace facebook { namespace thrift { namespace concurrency { */ class Mutex { public: - Mutex(); + typedef void (*Initializer)(void*); + + Mutex(Initializer init = DEFAULT_INITIALIZER); virtual ~Mutex() {} virtual void lock() const; virtual bool trylock() const; virtual void unlock() const; + static void DEFAULT_INITIALIZER(void*); +#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP + static void ADAPTIVE_INITIALIZER(void*); +#endif +#ifdef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP + static void RECURSIVE_INITIALIZER(void*); +#endif + private: class impl; -- 2.17.1