blob: eef97fd8159a03049e19af8024cfb5807c5f9e9c [file] [log] [blame]
Mark Slee9f0c6512007-02-28 23:58:26 +00001// Copyright (c) 2006- Facebook
2// Distributed under the Thrift Software License
3//
4// See accompanying file LICENSE or visit the Thrift site at:
5// http://developers.facebook.com/thrift/
6
Marc Slemko66949872006-07-15 01:52:39 +00007#include "Mutex.h"
8
9#include <assert.h>
10#include <pthread.h>
11
yunfang14542962007-10-03 22:59:41 +000012using boost::shared_ptr;
13
T Jake Lucianib5e62212009-01-31 22:36:20 +000014namespace apache { namespace thrift { namespace concurrency {
Marc Slemko66949872006-07-15 01:52:39 +000015
David Reiss0c90f6f2008-02-06 22:18:40 +000016/**
Mark Sleef5f2be42006-09-05 21:05:31 +000017 * Implementation of Mutex class using POSIX mutex
18 *
Mark Sleef5f2be42006-09-05 21:05:31 +000019 * @version $Id:$
20 */
Marc Slemko66949872006-07-15 01:52:39 +000021class Mutex::impl {
Mark Sleef5f2be42006-09-05 21:05:31 +000022 public:
David Reissc6dab612008-06-10 22:55:13 +000023 impl(Initializer init) : initialized_(false) {
24 init(&pthread_mutex_);
Mark Slee2f6404d2006-10-10 01:37:40 +000025 initialized_ = true;
Marc Slemko66949872006-07-15 01:52:39 +000026 }
27
28 ~impl() {
Mark Slee2f6404d2006-10-10 01:37:40 +000029 if (initialized_) {
30 initialized_ = false;
Aditya Agarwal9dc57402007-03-31 17:45:12 +000031 int ret = pthread_mutex_destroy(&pthread_mutex_);
Aditya Agarwal3f234da2007-04-01 01:19:57 +000032 assert(ret == 0);
Marc Slemko66949872006-07-15 01:52:39 +000033 }
34 }
35
Mark Slee2f6404d2006-10-10 01:37:40 +000036 void lock() const { pthread_mutex_lock(&pthread_mutex_); }
Marc Slemko66949872006-07-15 01:52:39 +000037
boz5362e702007-08-15 20:55:36 +000038 bool trylock() const { return (0 == pthread_mutex_trylock(&pthread_mutex_)); }
39
Mark Slee2f6404d2006-10-10 01:37:40 +000040 void unlock() const { pthread_mutex_unlock(&pthread_mutex_); }
Marc Slemko66949872006-07-15 01:52:39 +000041
Mark Sleef5f2be42006-09-05 21:05:31 +000042 private:
Mark Slee2f6404d2006-10-10 01:37:40 +000043 mutable pthread_mutex_t pthread_mutex_;
44 mutable bool initialized_;
Marc Slemko66949872006-07-15 01:52:39 +000045};
46
David Reissc6dab612008-06-10 22:55:13 +000047Mutex::Mutex(Initializer init) : impl_(new Mutex::impl(init)) {}
Marc Slemko66949872006-07-15 01:52:39 +000048
Mark Slee2f6404d2006-10-10 01:37:40 +000049void Mutex::lock() const { impl_->lock(); }
Marc Slemko66949872006-07-15 01:52:39 +000050
boz5362e702007-08-15 20:55:36 +000051bool Mutex::trylock() const { return impl_->trylock(); }
52
Mark Slee2f6404d2006-10-10 01:37:40 +000053void Mutex::unlock() const { impl_->unlock(); }
Marc Slemko66949872006-07-15 01:52:39 +000054
David Reissc6dab612008-06-10 22:55:13 +000055void Mutex::DEFAULT_INITIALIZER(void* arg) {
56 pthread_mutex_t* pthread_mutex = (pthread_mutex_t*)arg;
57 int ret = pthread_mutex_init(pthread_mutex, NULL);
58 assert(ret == 0);
59}
60
61static void init_with_kind(pthread_mutex_t* mutex, int kind) {
62 pthread_mutexattr_t mutexattr;
63 int ret = pthread_mutexattr_init(&mutexattr);
64 assert(ret == 0);
65
66 // Apparently, this can fail. Should we really be aborting?
67 ret = pthread_mutexattr_settype(&mutexattr, kind);
68 assert(ret == 0);
69
70 ret = pthread_mutex_init(mutex, &mutexattr);
71 assert(ret == 0);
72
73 ret = pthread_mutexattr_destroy(&mutexattr);
74 assert(ret == 0);
75}
76
77#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
78void Mutex::ADAPTIVE_INITIALIZER(void* arg) {
79 // From mysql source: mysys/my_thr_init.c
80 // Set mutex type to "fast" a.k.a "adaptive"
81 //
82 // In this case the thread may steal the mutex from some other thread
83 // that is waiting for the same mutex. This will save us some
84 // context switches but may cause a thread to 'starve forever' while
85 // waiting for the mutex (not likely if the code within the mutex is
86 // short).
87 init_with_kind((pthread_mutex_t*)arg, PTHREAD_MUTEX_ADAPTIVE_NP);
88}
89#endif
90
91#ifdef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
92void Mutex::RECURSIVE_INITIALIZER(void* arg) {
93 init_with_kind((pthread_mutex_t*)arg, PTHREAD_MUTEX_RECURSIVE_NP);
94}
95#endif
96
97
David Reiss0c90f6f2008-02-06 22:18:40 +000098/**
bozcce81842007-07-06 22:27:52 +000099 * Implementation of ReadWriteMutex class using POSIX rw lock
100 *
bozcce81842007-07-06 22:27:52 +0000101 * @version $Id:$
102 */
103class ReadWriteMutex::impl {
104public:
105 impl() : initialized_(false) {
106 int ret = pthread_rwlock_init(&rw_lock_, NULL);
107 assert(ret == 0);
108 initialized_ = true;
109 }
110
111 ~impl() {
112 if(initialized_) {
113 initialized_ = false;
114 int ret = pthread_rwlock_destroy(&rw_lock_);
115 assert(ret == 0);
116 }
117 }
118
119 void acquireRead() const { pthread_rwlock_rdlock(&rw_lock_); }
120
121 void acquireWrite() const { pthread_rwlock_wrlock(&rw_lock_); }
122
123 bool attemptRead() const { return pthread_rwlock_tryrdlock(&rw_lock_); }
124
125 bool attemptWrite() const { return pthread_rwlock_trywrlock(&rw_lock_); }
126
127 void release() const { pthread_rwlock_unlock(&rw_lock_); }
128
David Reiss0c90f6f2008-02-06 22:18:40 +0000129private:
bozcce81842007-07-06 22:27:52 +0000130 mutable pthread_rwlock_t rw_lock_;
131 mutable bool initialized_;
132};
133
134ReadWriteMutex::ReadWriteMutex() : impl_(new ReadWriteMutex::impl()) {}
135
136void ReadWriteMutex::acquireRead() const { impl_->acquireRead(); }
137
138void ReadWriteMutex::acquireWrite() const { impl_->acquireWrite(); }
139
140bool ReadWriteMutex::attemptRead() const { return impl_->attemptRead(); }
141
142bool ReadWriteMutex::attemptWrite() const { return impl_->attemptWrite(); }
143
144void ReadWriteMutex::release() const { impl_->release(); }
145
T Jake Lucianib5e62212009-01-31 22:36:20 +0000146}}} // apache::thrift::concurrency
Marc Slemko66949872006-07-15 01:52:39 +0000147