blob: af68db673e08218480ccbae1431b3d7e0e7b04c1 [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 *
19 * @author marc
20 * @version $Id:$
21 */
Marc Slemko66949872006-07-15 01:52:39 +000022class Mutex::impl {
Mark Sleef5f2be42006-09-05 21:05:31 +000023 public:
David Reissc6dab612008-06-10 22:55:13 +000024 impl(Initializer init) : initialized_(false) {
25 init(&pthread_mutex_);
Mark Slee2f6404d2006-10-10 01:37:40 +000026 initialized_ = true;
Marc Slemko66949872006-07-15 01:52:39 +000027 }
28
29 ~impl() {
Mark Slee2f6404d2006-10-10 01:37:40 +000030 if (initialized_) {
31 initialized_ = false;
Aditya Agarwal9dc57402007-03-31 17:45:12 +000032 int ret = pthread_mutex_destroy(&pthread_mutex_);
Aditya Agarwal3f234da2007-04-01 01:19:57 +000033 assert(ret == 0);
Marc Slemko66949872006-07-15 01:52:39 +000034 }
35 }
36
Mark Slee2f6404d2006-10-10 01:37:40 +000037 void lock() const { pthread_mutex_lock(&pthread_mutex_); }
Marc Slemko66949872006-07-15 01:52:39 +000038
boz5362e702007-08-15 20:55:36 +000039 bool trylock() const { return (0 == pthread_mutex_trylock(&pthread_mutex_)); }
40
Mark Slee2f6404d2006-10-10 01:37:40 +000041 void unlock() const { pthread_mutex_unlock(&pthread_mutex_); }
Marc Slemko66949872006-07-15 01:52:39 +000042
Mark Sleef5f2be42006-09-05 21:05:31 +000043 private:
Mark Slee2f6404d2006-10-10 01:37:40 +000044 mutable pthread_mutex_t pthread_mutex_;
45 mutable bool initialized_;
Marc Slemko66949872006-07-15 01:52:39 +000046};
47
David Reissc6dab612008-06-10 22:55:13 +000048Mutex::Mutex(Initializer init) : impl_(new Mutex::impl(init)) {}
Marc Slemko66949872006-07-15 01:52:39 +000049
Mark Slee2f6404d2006-10-10 01:37:40 +000050void Mutex::lock() const { impl_->lock(); }
Marc Slemko66949872006-07-15 01:52:39 +000051
boz5362e702007-08-15 20:55:36 +000052bool Mutex::trylock() const { return impl_->trylock(); }
53
Mark Slee2f6404d2006-10-10 01:37:40 +000054void Mutex::unlock() const { impl_->unlock(); }
Marc Slemko66949872006-07-15 01:52:39 +000055
David Reissc6dab612008-06-10 22:55:13 +000056void Mutex::DEFAULT_INITIALIZER(void* arg) {
57 pthread_mutex_t* pthread_mutex = (pthread_mutex_t*)arg;
58 int ret = pthread_mutex_init(pthread_mutex, NULL);
59 assert(ret == 0);
60}
61
62static void init_with_kind(pthread_mutex_t* mutex, int kind) {
63 pthread_mutexattr_t mutexattr;
64 int ret = pthread_mutexattr_init(&mutexattr);
65 assert(ret == 0);
66
67 // Apparently, this can fail. Should we really be aborting?
68 ret = pthread_mutexattr_settype(&mutexattr, kind);
69 assert(ret == 0);
70
71 ret = pthread_mutex_init(mutex, &mutexattr);
72 assert(ret == 0);
73
74 ret = pthread_mutexattr_destroy(&mutexattr);
75 assert(ret == 0);
76}
77
78#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
79void Mutex::ADAPTIVE_INITIALIZER(void* arg) {
80 // From mysql source: mysys/my_thr_init.c
81 // Set mutex type to "fast" a.k.a "adaptive"
82 //
83 // In this case the thread may steal the mutex from some other thread
84 // that is waiting for the same mutex. This will save us some
85 // context switches but may cause a thread to 'starve forever' while
86 // waiting for the mutex (not likely if the code within the mutex is
87 // short).
88 init_with_kind((pthread_mutex_t*)arg, PTHREAD_MUTEX_ADAPTIVE_NP);
89}
90#endif
91
92#ifdef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
93void Mutex::RECURSIVE_INITIALIZER(void* arg) {
94 init_with_kind((pthread_mutex_t*)arg, PTHREAD_MUTEX_RECURSIVE_NP);
95}
96#endif
97
98
David Reiss0c90f6f2008-02-06 22:18:40 +000099/**
bozcce81842007-07-06 22:27:52 +0000100 * Implementation of ReadWriteMutex class using POSIX rw lock
101 *
102 * @author boz
103 * @version $Id:$
104 */
105class ReadWriteMutex::impl {
106public:
107 impl() : initialized_(false) {
108 int ret = pthread_rwlock_init(&rw_lock_, NULL);
109 assert(ret == 0);
110 initialized_ = true;
111 }
112
113 ~impl() {
114 if(initialized_) {
115 initialized_ = false;
116 int ret = pthread_rwlock_destroy(&rw_lock_);
117 assert(ret == 0);
118 }
119 }
120
121 void acquireRead() const { pthread_rwlock_rdlock(&rw_lock_); }
122
123 void acquireWrite() const { pthread_rwlock_wrlock(&rw_lock_); }
124
125 bool attemptRead() const { return pthread_rwlock_tryrdlock(&rw_lock_); }
126
127 bool attemptWrite() const { return pthread_rwlock_trywrlock(&rw_lock_); }
128
129 void release() const { pthread_rwlock_unlock(&rw_lock_); }
130
David Reiss0c90f6f2008-02-06 22:18:40 +0000131private:
bozcce81842007-07-06 22:27:52 +0000132 mutable pthread_rwlock_t rw_lock_;
133 mutable bool initialized_;
134};
135
136ReadWriteMutex::ReadWriteMutex() : impl_(new ReadWriteMutex::impl()) {}
137
138void ReadWriteMutex::acquireRead() const { impl_->acquireRead(); }
139
140void ReadWriteMutex::acquireWrite() const { impl_->acquireWrite(); }
141
142bool ReadWriteMutex::attemptRead() const { return impl_->attemptRead(); }
143
144bool ReadWriteMutex::attemptWrite() const { return impl_->attemptWrite(); }
145
146void ReadWriteMutex::release() const { impl_->release(); }
147
T Jake Lucianib5e62212009-01-31 22:36:20 +0000148}}} // apache::thrift::concurrency
Marc Slemko66949872006-07-15 01:52:39 +0000149