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 
44 namespace BLOCXX_NAMESPACE
45 {
46 
47 namespace MutexImpl
48 {
49 
50 #if defined (BLOCXX_USE_PTHREAD)
51 
52 #if !defined (BLOCXX_NCR)
53 
59 int
60 createMutex(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 
103 int
104 createMutex(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 
157 int
158 destroyMutex(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 
186 int
187 acquireMutex(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 
235 int
236 releaseMutex(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 
274 int
275 createMutex(Mutex_t& handle)
276 {
277  handle = new CRITICAL_SECTION;
278  assert(handle);
279  InitializeCriticalSection(handle);
280  return 0;
281 }
282 
283 int
284 destroyMutex(Mutex_t& handle)
285 {
286  if(handle)
287  {
288  DeleteCriticalSection(handle);
289  delete handle;
290  handle = 0;
291  }
292  return 0;
293 }
294 
295 int
296 acquireMutex(Mutex_t& handle)
297 {
298  EnterCriticalSection(handle);
299  return 0;
300 }
301 
302 int
303 releaseMutex(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