blob: 67d7a2cb6868426de6bdf158147388043f51c4e4 [file] [log] [blame]
David Reissea2cba82009-03-30 21:35:00 +00001/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
Mark Slee9f0c6512007-02-28 23:58:26 +000019
Marc Slemko66949872006-07-15 01:52:39 +000020#include "Mutex.h"
David Reiss4e19f192010-03-09 05:19:59 +000021#include "Util.h"
Marc Slemko66949872006-07-15 01:52:39 +000022
23#include <assert.h>
24#include <pthread.h>
25
yunfang14542962007-10-03 22:59:41 +000026using boost::shared_ptr;
27
T Jake Lucianib5e62212009-01-31 22:36:20 +000028namespace apache { namespace thrift { namespace concurrency {
Marc Slemko66949872006-07-15 01:52:39 +000029
David Reiss0c90f6f2008-02-06 22:18:40 +000030/**
Mark Sleef5f2be42006-09-05 21:05:31 +000031 * Implementation of Mutex class using POSIX mutex
32 *
Mark Sleef5f2be42006-09-05 21:05:31 +000033 * @version $Id:$
34 */
Marc Slemko66949872006-07-15 01:52:39 +000035class Mutex::impl {
Mark Sleef5f2be42006-09-05 21:05:31 +000036 public:
David Reissc6dab612008-06-10 22:55:13 +000037 impl(Initializer init) : initialized_(false) {
38 init(&pthread_mutex_);
Mark Slee2f6404d2006-10-10 01:37:40 +000039 initialized_ = true;
Marc Slemko66949872006-07-15 01:52:39 +000040 }
41
42 ~impl() {
Mark Slee2f6404d2006-10-10 01:37:40 +000043 if (initialized_) {
44 initialized_ = false;
Aditya Agarwal9dc57402007-03-31 17:45:12 +000045 int ret = pthread_mutex_destroy(&pthread_mutex_);
Aditya Agarwal3f234da2007-04-01 01:19:57 +000046 assert(ret == 0);
Marc Slemko66949872006-07-15 01:52:39 +000047 }
48 }
49
Mark Slee2f6404d2006-10-10 01:37:40 +000050 void lock() const { pthread_mutex_lock(&pthread_mutex_); }
Marc Slemko66949872006-07-15 01:52:39 +000051
boz5362e702007-08-15 20:55:36 +000052 bool trylock() const { return (0 == pthread_mutex_trylock(&pthread_mutex_)); }
53
David Reiss4e19f192010-03-09 05:19:59 +000054 bool timedlock(int64_t milliseconds) const {
55 struct timespec ts;
56 Util::toTimespec(ts, milliseconds);
57 return (0 == pthread_mutex_timedlock(&pthread_mutex_, &ts));
58 }
59
Mark Slee2f6404d2006-10-10 01:37:40 +000060 void unlock() const { pthread_mutex_unlock(&pthread_mutex_); }
Marc Slemko66949872006-07-15 01:52:39 +000061
David Reissb9db49c2010-03-09 05:19:30 +000062 void* getUnderlyingImpl() const { return (void*) &pthread_mutex_; }
63
Mark Sleef5f2be42006-09-05 21:05:31 +000064 private:
Mark Slee2f6404d2006-10-10 01:37:40 +000065 mutable pthread_mutex_t pthread_mutex_;
66 mutable bool initialized_;
Marc Slemko66949872006-07-15 01:52:39 +000067};
68
David Reissc6dab612008-06-10 22:55:13 +000069Mutex::Mutex(Initializer init) : impl_(new Mutex::impl(init)) {}
Marc Slemko66949872006-07-15 01:52:39 +000070
David Reissb9db49c2010-03-09 05:19:30 +000071void* Mutex::getUnderlyingImpl() const { return impl_->getUnderlyingImpl(); }
72
Mark Slee2f6404d2006-10-10 01:37:40 +000073void Mutex::lock() const { impl_->lock(); }
Marc Slemko66949872006-07-15 01:52:39 +000074
boz5362e702007-08-15 20:55:36 +000075bool Mutex::trylock() const { return impl_->trylock(); }
76
David Reiss4e19f192010-03-09 05:19:59 +000077bool Mutex::timedlock(int64_t ms) const { return impl_->timedlock(ms); }
78
Mark Slee2f6404d2006-10-10 01:37:40 +000079void Mutex::unlock() const { impl_->unlock(); }
Marc Slemko66949872006-07-15 01:52:39 +000080
David Reissc6dab612008-06-10 22:55:13 +000081void Mutex::DEFAULT_INITIALIZER(void* arg) {
82 pthread_mutex_t* pthread_mutex = (pthread_mutex_t*)arg;
83 int ret = pthread_mutex_init(pthread_mutex, NULL);
84 assert(ret == 0);
85}
86
87static void init_with_kind(pthread_mutex_t* mutex, int kind) {
88 pthread_mutexattr_t mutexattr;
89 int ret = pthread_mutexattr_init(&mutexattr);
90 assert(ret == 0);
91
92 // Apparently, this can fail. Should we really be aborting?
93 ret = pthread_mutexattr_settype(&mutexattr, kind);
94 assert(ret == 0);
95
96 ret = pthread_mutex_init(mutex, &mutexattr);
97 assert(ret == 0);
98
99 ret = pthread_mutexattr_destroy(&mutexattr);
100 assert(ret == 0);
101}
102
103#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
104void Mutex::ADAPTIVE_INITIALIZER(void* arg) {
105 // From mysql source: mysys/my_thr_init.c
106 // Set mutex type to "fast" a.k.a "adaptive"
107 //
108 // In this case the thread may steal the mutex from some other thread
109 // that is waiting for the same mutex. This will save us some
110 // context switches but may cause a thread to 'starve forever' while
111 // waiting for the mutex (not likely if the code within the mutex is
112 // short).
113 init_with_kind((pthread_mutex_t*)arg, PTHREAD_MUTEX_ADAPTIVE_NP);
114}
115#endif
116
117#ifdef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
118void Mutex::RECURSIVE_INITIALIZER(void* arg) {
119 init_with_kind((pthread_mutex_t*)arg, PTHREAD_MUTEX_RECURSIVE_NP);
120}
121#endif
122
123
David Reiss0c90f6f2008-02-06 22:18:40 +0000124/**
bozcce81842007-07-06 22:27:52 +0000125 * Implementation of ReadWriteMutex class using POSIX rw lock
126 *
bozcce81842007-07-06 22:27:52 +0000127 * @version $Id:$
128 */
129class ReadWriteMutex::impl {
130public:
131 impl() : initialized_(false) {
132 int ret = pthread_rwlock_init(&rw_lock_, NULL);
133 assert(ret == 0);
134 initialized_ = true;
135 }
136
137 ~impl() {
138 if(initialized_) {
139 initialized_ = false;
140 int ret = pthread_rwlock_destroy(&rw_lock_);
141 assert(ret == 0);
142 }
143 }
144
145 void acquireRead() const { pthread_rwlock_rdlock(&rw_lock_); }
146
147 void acquireWrite() const { pthread_rwlock_wrlock(&rw_lock_); }
148
149 bool attemptRead() const { return pthread_rwlock_tryrdlock(&rw_lock_); }
150
151 bool attemptWrite() const { return pthread_rwlock_trywrlock(&rw_lock_); }
152
153 void release() const { pthread_rwlock_unlock(&rw_lock_); }
154
David Reiss0c90f6f2008-02-06 22:18:40 +0000155private:
bozcce81842007-07-06 22:27:52 +0000156 mutable pthread_rwlock_t rw_lock_;
157 mutable bool initialized_;
158};
159
160ReadWriteMutex::ReadWriteMutex() : impl_(new ReadWriteMutex::impl()) {}
161
162void ReadWriteMutex::acquireRead() const { impl_->acquireRead(); }
163
164void ReadWriteMutex::acquireWrite() const { impl_->acquireWrite(); }
165
166bool ReadWriteMutex::attemptRead() const { return impl_->attemptRead(); }
167
168bool ReadWriteMutex::attemptWrite() const { return impl_->attemptWrite(); }
169
170void ReadWriteMutex::release() const { impl_->release(); }
171
T Jake Lucianib5e62212009-01-31 22:36:20 +0000172}}} // apache::thrift::concurrency
Marc Slemko66949872006-07-15 01:52:39 +0000173