blob: 045dbdfe2d62d7dd62b034b8caaba29056438cd6 [file] [log] [blame]
Gavin McDonald0b75e1a2010-10-28 02:12:01 +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 */
19
20#include "Mutex.h"
21
22#include <assert.h>
23#include <pthread.h>
24
25using boost::shared_ptr;
26
27namespace apache { namespace thrift { namespace concurrency {
28
29/**
30 * Implementation of Mutex class using POSIX mutex
31 *
32 * @version $Id:$
33 */
34class Mutex::impl {
35 public:
36 impl(Initializer init) : initialized_(false) {
37 init(&pthread_mutex_);
38 initialized_ = true;
39 }
40
41 ~impl() {
42 if (initialized_) {
43 initialized_ = false;
44 int ret = pthread_mutex_destroy(&pthread_mutex_);
45 assert(ret == 0);
46 }
47 }
48
49 void lock() const { pthread_mutex_lock(&pthread_mutex_); }
50
51 bool trylock() const { return (0 == pthread_mutex_trylock(&pthread_mutex_)); }
52
53 void unlock() const { pthread_mutex_unlock(&pthread_mutex_); }
54
55 private:
56 mutable pthread_mutex_t pthread_mutex_;
57 mutable bool initialized_;
58};
59
60Mutex::Mutex(Initializer init) : impl_(new Mutex::impl(init)) {}
61
62void Mutex::lock() const { impl_->lock(); }
63
64bool Mutex::trylock() const { return impl_->trylock(); }
65
66void Mutex::unlock() const { impl_->unlock(); }
67
68void Mutex::DEFAULT_INITIALIZER(void* arg) {
69 pthread_mutex_t* pthread_mutex = (pthread_mutex_t*)arg;
70 int ret = pthread_mutex_init(pthread_mutex, NULL);
71 assert(ret == 0);
72}
73
74static void init_with_kind(pthread_mutex_t* mutex, int kind) {
75 pthread_mutexattr_t mutexattr;
76 int ret = pthread_mutexattr_init(&mutexattr);
77 assert(ret == 0);
78
79 // Apparently, this can fail. Should we really be aborting?
80 ret = pthread_mutexattr_settype(&mutexattr, kind);
81 assert(ret == 0);
82
83 ret = pthread_mutex_init(mutex, &mutexattr);
84 assert(ret == 0);
85
86 ret = pthread_mutexattr_destroy(&mutexattr);
87 assert(ret == 0);
88}
89
90#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
91void Mutex::ADAPTIVE_INITIALIZER(void* arg) {
92 // From mysql source: mysys/my_thr_init.c
93 // Set mutex type to "fast" a.k.a "adaptive"
94 //
95 // In this case the thread may steal the mutex from some other thread
96 // that is waiting for the same mutex. This will save us some
97 // context switches but may cause a thread to 'starve forever' while
98 // waiting for the mutex (not likely if the code within the mutex is
99 // short).
100 init_with_kind((pthread_mutex_t*)arg, PTHREAD_MUTEX_ADAPTIVE_NP);
101}
102#endif
103
104#ifdef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
105void Mutex::RECURSIVE_INITIALIZER(void* arg) {
106 init_with_kind((pthread_mutex_t*)arg, PTHREAD_MUTEX_RECURSIVE_NP);
107}
108#endif
109
110
111/**
112 * Implementation of ReadWriteMutex class using POSIX rw lock
113 *
114 * @version $Id:$
115 */
116class ReadWriteMutex::impl {
117public:
118 impl() : initialized_(false) {
119 int ret = pthread_rwlock_init(&rw_lock_, NULL);
120 assert(ret == 0);
121 initialized_ = true;
122 }
123
124 ~impl() {
125 if(initialized_) {
126 initialized_ = false;
127 int ret = pthread_rwlock_destroy(&rw_lock_);
128 assert(ret == 0);
129 }
130 }
131
132 void acquireRead() const { pthread_rwlock_rdlock(&rw_lock_); }
133
134 void acquireWrite() const { pthread_rwlock_wrlock(&rw_lock_); }
135
136 bool attemptRead() const { return pthread_rwlock_tryrdlock(&rw_lock_); }
137
138 bool attemptWrite() const { return pthread_rwlock_trywrlock(&rw_lock_); }
139
140 void release() const { pthread_rwlock_unlock(&rw_lock_); }
141
142private:
143 mutable pthread_rwlock_t rw_lock_;
144 mutable bool initialized_;
145};
146
147ReadWriteMutex::ReadWriteMutex() : impl_(new ReadWriteMutex::impl()) {}
148
149void ReadWriteMutex::acquireRead() const { impl_->acquireRead(); }
150
151void ReadWriteMutex::acquireWrite() const { impl_->acquireWrite(); }
152
153bool ReadWriteMutex::attemptRead() const { return impl_->attemptRead(); }
154
155bool ReadWriteMutex::attemptWrite() const { return impl_->attemptWrite(); }
156
157void ReadWriteMutex::release() const { impl_->release(); }
158
159}}} // apache::thrift::concurrency
160