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
diff --git a/lib/cpp/src/concurrency/Mutex.cpp b/lib/cpp/src/concurrency/Mutex.cpp
index 87bfd35..b160b67 100644
--- a/lib/cpp/src/concurrency/Mutex.cpp
+++ b/lib/cpp/src/concurrency/Mutex.cpp
@@ -21,9 +21,8 @@
  */
 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 @@
   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 @@
 
 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 e176628..7830d68 100644
--- a/lib/cpp/src/concurrency/Mutex.h
+++ b/lib/cpp/src/concurrency/Mutex.h
@@ -19,12 +19,22 @@
  */
 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;