blocxx
MutexImpl.cpp
Go to the documentation of this file.
1/*******************************************************************************
2* Copyright (C) 2005, Vintela, Inc. All rights reserved.
3* Copyright (C) 2006, Novell, Inc. All rights reserved.
4*
5* Redistribution and use in source and binary forms, with or without
6* modification, are permitted provided that the following conditions are met:
7*
8* * Redistributions of source code must retain the above copyright notice,
9* this list of conditions and the following disclaimer.
10* * Redistributions in binary form must reproduce the above copyright
11* notice, this list of conditions and the following disclaimer in the
12* documentation and/or other materials provided with the distribution.
13* * Neither the name of
14* Vintela, Inc.,
15* nor Novell, Inc.,
16* nor the names of its contributors or employees may be used to
17* endorse or promote products derived from this software without
18* specific prior written permission.
19*
20* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30* POSSIBILITY OF SUCH DAMAGE.
31*******************************************************************************/
32
33
39#include "blocxx/BLOCXX_config.h"
40#include "blocxx/MutexImpl.hpp"
41#include <cerrno>
42#include <cassert>
43
44namespace BLOCXX_NAMESPACE
45{
46
47namespace MutexImpl
48{
49
50#if defined (BLOCXX_USE_PTHREAD)
51
52#if !defined (BLOCXX_NCR)
53
59int
60createMutex(Mutex_t& handle)
61{
62 pthread_mutexattr_t attr;
63 int res = pthread_mutexattr_init(&attr);
64 assert(res == 0);
65 if (res != 0)
66 {
67 return -1;
68 }
69
70#if defined(BLOCXX_HAVE_PTHREAD_MUTEXATTR_SETTYPE)
71 res = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
72 assert(res == 0);
73 if (res != 0)
74 {
75 pthread_mutexattr_destroy(&attr);
76 return -1;
77 }
78#endif
79
80 res = pthread_mutex_init(&handle.mutex, &attr);
81 pthread_mutexattr_destroy(&attr);
82 if (res != 0)
83 {
84 return -1;
85 }
86
87#if !defined(BLOCXX_HAVE_PTHREAD_MUTEXATTR_SETTYPE)
88 res = pthread_cond_init(&handle.unlocked, PTHREAD_COND_ATTR_DEFAULT);
89 if (res != 0)
90 {
91 pthread_mutex_destroy(&handle.mutex);
92 return -1;
93 }
94
95 handle.valid_id = false;
96 handle.count = 0;
97#endif
98 return 0;
99}
100
101#else //#if !defined (BLOCXX_NCR)
102
103int
104createMutex(Mutex_t& handle)
105{
106 pthread_mutexattr_t attr;
107 int res = pthread_mutexattr_create(&attr);
108 assert(res == 0);
109 if (res != 0)
110 {
111 return -1;
112 }
113
114#if defined(BLOCXX_HAVE_PTHREAD_MUTEXATTR_SETTYPE)
115 res = pthread_mutexattr_setkind_np(&attr, MUTEX_RECURSIVE_NP);
116 assert(res == 0);
117 if (res != 0)
118 {
119 pthread_mutexattr_delete(&attr);
120 return -1;
121 }
122#endif
123
124 res = pthread_mutex_init(&handle.mutex, attr);
125
126 pthread_mutexattr_delete(&attr);
127 if (res != 0)
128 {
129 return -1;
130 }
131
132#if !defined(BLOCXX_HAVE_PTHREAD_MUTEXATTR_SETTYPE)
133 res = pthread_cond_init(&handle.unlocked, PTHREAD_COND_ATTR_DEFAULT);
134 if (res != 0)
135 {
136 pthread_mutex_destroy(&handle.mutex);
137 return -1;
138 }
139
140 handle.valid_id = false;
141 handle.count = 0;
142#endif
143 return 0;
144}
145
146#endif //#ifndef BLOCXX_NCR
147
157int
158destroyMutex(Mutex_t& handle)
159{
160 switch (pthread_mutex_destroy(&handle.mutex))
161 {
162 case 0:
163 break;
164 case EBUSY:
165 return -1;
166 break;
167 default:
168 return -2;
169 }
170 int res = 0;
171#if !defined(BLOCXX_HAVE_PTHREAD_MUTEXATTR_SETTYPE)
172 res = pthread_cond_destroy(&handle.unlocked);
173 assert(res == 0);
174#endif
175 return res;
176}
177
186int
187acquireMutex(Mutex_t& handle)
188{
189 int res = pthread_mutex_lock(&handle.mutex);
190 assert(res == 0);
191
192#if !defined(BLOCXX_HAVE_PTHREAD_MUTEXATTR_SETTYPE)
193 pthread_t tid = pthread_self();
194 if (handle.valid_id && pthread_equal(handle.thread_id, tid))
195 {
196 ++handle.count;
197 }
198 else
199 {
200 while (handle.valid_id)
201 {
202 res = pthread_cond_wait(&handle.unlocked, &handle.mutex);
203 assert(res == 0 || res == EINTR);
204 if (res == EINTR)
205 {
206 try
207 {
209 }
210 catch (...)
211 {
212 pthread_mutex_unlock(&handle.mutex);
213 throw;
214 }
215 }
216 }
217
218 handle.thread_id = tid;
219 handle.valid_id = true;
220 handle.count = 1;
221 }
222
223 res = pthread_mutex_unlock(&handle.mutex);
224 assert(res == 0);
225#endif
226 return res;
227}
228
235int
236releaseMutex(Mutex_t& handle)
237{
238#if defined(BLOCXX_HAVE_PTHREAD_MUTEXATTR_SETTYPE)
239 int res = pthread_mutex_unlock(&handle.mutex);
240 assert(res == 0);
241 return res;
242#else
243 int res = 0;
244 res = pthread_mutex_lock(&handle.mutex);
245 assert(res == 0);
246
247 pthread_t tid = pthread_self();
248 if (handle.valid_id && !pthread_equal(handle.thread_id, tid))
249 {
250 res = pthread_mutex_unlock(&handle.mutex);
251 assert(res == 0);
252 return -1;
253 }
254
255 if (--handle.count == 0)
256 {
257 assert(handle.valid_id);
258 handle.valid_id = false;
259
260 res = pthread_cond_signal(&handle.unlocked);
261 assert(res == 0);
262 }
263
264 res = pthread_mutex_unlock(&handle.mutex);
265 assert(res == 0);
266 return res;
267#endif //#if defined(BLOCXX_HAVE_PTHREAD_MUTEXATTR_SETTYPE)
268}
269
270#endif //#if defined (BLOCXX_USE_PTHREAD)
271
272#if defined(BLOCXX_WIN32)
273
274int
275createMutex(Mutex_t& handle)
276{
277 handle = new CRITICAL_SECTION;
278 assert(handle);
279 InitializeCriticalSection(handle);
280 return 0;
281}
282
283int
284destroyMutex(Mutex_t& handle)
285{
286 if(handle)
287 {
288 DeleteCriticalSection(handle);
289 delete handle;
290 handle = 0;
291 }
292 return 0;
293}
294
295int
296acquireMutex(Mutex_t& handle)
297{
298 EnterCriticalSection(handle);
299 return 0;
300}
301
302int
303releaseMutex(Mutex_t& handle)
304{
305 LeaveCriticalSection(handle);
306 return 0;
307}
308
309#endif //#if defined(BLOCXX_WIN32)
310
311} // end namespace MutexImpl
312} // end namespace BLOCXX_NAMESPACE
313
static void testCancel()
Test if this thread has been cancelled.
Definition Thread.cpp:432
BLOCXX_COMMON_API int acquireMutex(Mutex_t &handle)
Acquire the mutex specified by a given mutex handle.
BLOCXX_COMMON_API int destroyMutex(Mutex_t &handle)
Destroy a mutex previously created with createMutex.
BLOCXX_COMMON_API int releaseMutex(Mutex_t &handle)
Release a mutex that was previously acquired with the acquireMutex method.
BLOCXX_COMMON_API int createMutex(Mutex_t &handle)
Create a platform specific mutext handle.
Taken from RFC 1321.