CLAM-Development  1.4.0
RecursiveMutex.cxx
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2004 MUSIC TECHNOLOGY GROUP (MTG)
3  * UNIVERSITAT POMPEU FABRA
4  *
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  *
20  */
21 
22 #include "RecursiveMutex.hxx"
23 #include "xtime.hxx"
24 #include "Assert.hxx"
25 #include <pthread.h>
26 #include <errno.h>
27 
28 namespace CLAM
29 {
30 
31 
33  : mCount(0), mValidID( false )
34  {
35  pthread_mutexattr_t attr;
36 
37  int res = 0;
38 
39  res = pthread_mutexattr_init( &attr );
40  CLAM_ASSERT( res == 0, "pthread_mutexattr_init failed" );
41 
42  res = pthread_mutex_init( &mMutex, &attr );
43  CLAM_ASSERT( res == 0, "pthread_mutex_init failed");
44 
45  res = pthread_cond_init( &mUnlocked, 0 );
46 
47  if ( res!= 0 )
48  {
49  pthread_mutex_destroy( &mMutex );
50  throw ThreadResourceError("pthread_cond_init failed");
51  }
52  }
53 
55  {
56  int res = 0;
57  res = pthread_mutex_destroy( &mMutex );
58 
59  CLAM_ASSERT( res == 0, "pthread_mutex_destroy failed" );
60 
61  res = pthread_cond_destroy( &mUnlocked );
62 
63  CLAM_ASSERT( res == 0, "pthread_cond_destroy failed" );
64  }
65 
66 
67  void RecursiveMutex::DoLock()
68  {
69  int res = 0;
70 
71  res = pthread_mutex_lock( &mMutex );
72 
73  pthread_t tid = pthread_self();
74 
75  if ( mValidID && pthread_equal( mThreadID, tid ) )
76  ++ mCount;
77  else
78  {
79  while ( mValidID )
80  {
81  res = pthread_cond_wait( &mUnlocked, &mMutex );
82  CLAM_ASSERT( res == 0, "pthread_cond_wait failed" );
83  }
84 
85  mThreadID = tid;
86  mValidID = true;
87  mCount = 1;
88  }
89 
90  res = pthread_mutex_unlock( &mMutex );
91  CLAM_ASSERT( res == 0, "pthread_mutex_unlock failed" );
92  }
93 
94  void RecursiveMutex::DoUnlock( )
95  {
96  int res = 0;
97  res = pthread_mutex_lock( &mMutex );
98  CLAM_ASSERT( res == 0, "pthread_mutex_lock failed" );
99 
100  pthread_t tid = pthread_self();
101 
102  if ( mValidID && !pthread_equal( mThreadID, tid ) )
103  {
104  res = pthread_mutex_unlock( &mMutex );
105  CLAM_ASSERT( res == 0, "pthread_mutex_unlock failed" );
106  }
107 
108  if ( --mCount == 0 )
109  {
110  CLAM_ASSERT( mValidID, "Spurious value change!" );
111  mValidID = false;
112 
113  res = pthread_cond_signal( &mUnlocked );
114  CLAM_ASSERT( res==0, "pthread_cond_signal failed" );
115  }
116 
117  res = pthread_mutex_unlock( &mMutex );
118  CLAM_ASSERT( res == 0, "pthread_mutex_unlock failed" );
119  }
120 
121  void RecursiveMutex::DoLock( ConditionVar& state )
122  {
123  int res = 0;
124 
125  while ( mValidID )
126  {
127  res = pthread_cond_wait( &mUnlocked, &mMutex );
128  CLAM_ASSERT( res == 0, "pthread_cond_wait failed!" );
129  }
130 
131  mThreadID = pthread_self();
132  mValidID = true;
133  mCount = state.count;
134 
135  res = pthread_mutex_unlock( &mMutex );
136  CLAM_ASSERT( res == 0, "pthread_mutex_unlock failed" );
137  }
138 
139  void RecursiveMutex::DoUnlock( ConditionVar& state )
140  {
141  int res = 0;
142 
143  res = pthread_mutex_lock( &mMutex );
144  CLAM_ASSERT( res == 0, "pthread_mutex_lock failed" );
145 
146  CLAM_ASSERT( mValidID, "Spurious value change!" );
147  mValidID = false;
148 
149  res = pthread_cond_signal( &mUnlocked );
150  CLAM_ASSERT( res == 0, "pthread_cond_signal failed!" );
151 
152  state.pmutex = &mMutex;
153  state.count = mCount;
154  }
155 
157  : mCount(0), mValidID( false )
158  {
159  pthread_mutexattr_t attr;
160 
161  int res = 0;
162 
163  res = pthread_mutexattr_init( &attr );
164  CLAM_ASSERT( res == 0, "pthread_mutexattr_init failed" );
165 
166  res = pthread_mutex_init( &mMutex, &attr );
167  CLAM_ASSERT( res == 0, "pthread_mutex_init failed");
168 
169  res = pthread_cond_init( &mUnlocked, 0 );
170 
171  if ( res!= 0 )
172  {
173  pthread_mutex_destroy( &mMutex );
174  throw ThreadResourceError("pthread_cond_init failed");
175  }
176  }
177 
179  {
180  int res = 0;
181  res = pthread_mutex_destroy( &mMutex );
182 
183  CLAM_ASSERT( res == 0, "pthread_mutex_destroy failed" );
184 
185  res = pthread_cond_destroy( &mUnlocked );
186 
187  CLAM_ASSERT( res == 0, "pthread_cond_destroy failed" );
188  }
189 
190 
191  void RecursiveTryMutex::DoLock()
192  {
193  int res = 0;
194 
195  res = pthread_mutex_lock( &mMutex );
196 
197  pthread_t tid = pthread_self();
198 
199  if ( mValidID && pthread_equal( mThreadID, tid ) )
200  ++ mCount;
201  else
202  {
203  while ( mValidID )
204  {
205  res = pthread_cond_wait( &mUnlocked, &mMutex );
206  CLAM_ASSERT( res == 0, "pthread_cond_wait failed" );
207  }
208 
209  mThreadID = tid;
210  mValidID = true;
211  mCount = 1;
212  }
213 
214  res = pthread_mutex_unlock( &mMutex );
215  CLAM_ASSERT( res == 0, "pthread_mutex_unlock failed" );
216  }
217 
218  bool RecursiveTryMutex::DoTryLock()
219  {
220  int res = 0;
221 
222  res = pthread_mutex_lock( &mMutex );
223  CLAM_ASSERT( res == 0, " pthread_mutex_lock failed " );
224 
225  bool ret = false;
226 
227  pthread_t tid = pthread_self();
228 
229  if (mValidID && pthread_equal(mThreadID, tid ) )
230  {
231  ++mCount;
232  ret = true;
233  }
234  else if ( !mValidID )
235  {
236  mThreadID = tid;
237  mValidID = true;
238  mCount = 1;
239  ret = true;
240  }
241 
242  res = pthread_mutex_unlock(&mMutex );
243  CLAM_ASSERT( res==0, "pthread_mutex_unlock failed" );
244 
245  return ret;
246  }
247 
248  void RecursiveTryMutex::DoUnlock( )
249  {
250  int res = 0;
251  res = pthread_mutex_lock( &mMutex );
252  CLAM_ASSERT( res == 0, "pthread_mutex_lock failed" );
253 
254  pthread_t tid = pthread_self();
255 
256  if ( mValidID && !pthread_equal( mThreadID, tid ) )
257  {
258  res = pthread_mutex_unlock( &mMutex );
259  CLAM_ASSERT( res == 0, "pthread_mutex_unlock failed" );
260  }
261 
262  if ( --mCount == 0 )
263  {
264  CLAM_ASSERT( mValidID, "Spurious value change!" );
265  mValidID = false;
266 
267  res = pthread_cond_signal( &mUnlocked );
268  CLAM_ASSERT( res==0, "pthread_cond_signal failed" );
269  }
270 
271  res = pthread_mutex_unlock( &mMutex );
272  CLAM_ASSERT( res == 0, "pthread_mutex_unlock failed" );
273  }
274 
275  void RecursiveTryMutex::DoLock( ConditionVar& state )
276  {
277  int res = 0;
278 
279  while ( mValidID )
280  {
281  res = pthread_cond_wait( &mUnlocked, &mMutex );
282  CLAM_ASSERT( res == 0, "pthread_cond_wait failed!" );
283  }
284 
285  mThreadID = pthread_self();
286  mValidID = true;
287  mCount = state.count;
288 
289  res = pthread_mutex_unlock( &mMutex );
290  CLAM_ASSERT( res == 0, "pthread_mutex_unlock failed" );
291  }
292 
293  void RecursiveTryMutex::DoUnlock( ConditionVar& state )
294  {
295  int res = 0;
296 
297  res = pthread_mutex_lock( &mMutex );
298  CLAM_ASSERT( res == 0, "pthread_mutex_lock failed" );
299 
300  CLAM_ASSERT( mValidID, "Spurious value change!" );
301  mValidID = false;
302 
303  res = pthread_cond_signal( &mUnlocked );
304  CLAM_ASSERT( res == 0, "pthread_cond_signal failed!" );
305 
306  state.pmutex = &mMutex;
307  state.count = mCount;
308  }
309 
310 
312  : mCount(0), mValidID( false )
313  {
314  pthread_mutexattr_t attr;
315 
316  int res = 0;
317 
318  res = pthread_mutexattr_init( &attr );
319  CLAM_ASSERT( res == 0, "pthread_mutexattr_init failed" );
320 
321 
322  res = pthread_mutex_init( &mMutex, &attr );
323  CLAM_ASSERT( res == 0, "pthread_mutex_init failed");
324 
325  res = pthread_cond_init( &mUnlocked, 0 );
326 
327  if ( res!= 0 )
328  {
329  pthread_mutex_destroy( &mMutex );
330  throw ThreadResourceError("pthread_cond_init failed");
331  }
332  }
333 
335  {
336  int res = 0;
337  res = pthread_mutex_destroy( &mMutex );
338 
339  CLAM_ASSERT( res == 0, "pthread_mutex_destroy failed" );
340 
341  res = pthread_cond_destroy( &mUnlocked );
342 
343  CLAM_ASSERT( res == 0, "pthread_cond_destroy failed" );
344  }
345 
346 
347  void RecursiveTimedMutex::DoLock()
348  {
349  int res = 0;
350 
351  res = pthread_mutex_lock( &mMutex );
352 
353  pthread_t tid = pthread_self();
354 
355  if ( mValidID && pthread_equal( mThreadID, tid ) )
356  ++ mCount;
357  else
358  {
359  while ( mValidID )
360  {
361  res = pthread_cond_wait( &mUnlocked, &mMutex );
362  CLAM_ASSERT( res == 0, "pthread_cond_wait failed" );
363  }
364 
365  mThreadID = tid;
366  mValidID = true;
367  mCount = 1;
368  }
369 
370  res = pthread_mutex_unlock( &mMutex );
371  CLAM_ASSERT( res == 0, "pthread_mutex_unlock failed" );
372  }
373 
374  bool RecursiveTimedMutex::DoTryLock()
375  {
376  int res = 0;
377 
378  res = pthread_mutex_lock( &mMutex );
379  CLAM_ASSERT( res == 0, " pthread_mutex_lock failed " );
380 
381  bool ret = false;
382 
383  pthread_t tid = pthread_self();
384 
385  if (mValidID && pthread_equal(mThreadID, tid ) )
386  {
387  ++mCount;
388  ret = true;
389  }
390  else if ( !mValidID )
391  {
392  mThreadID = tid;
393  mValidID = true;
394  mCount = 1;
395  ret = true;
396  }
397 
398  res = pthread_mutex_unlock(&mMutex );
399  CLAM_ASSERT( res==0, "pthread_mutex_unlock failed" );
400 
401  return ret;
402  }
403 
404  bool RecursiveTimedMutex::DoTimedLock( const xtime& xt )
405  {
406  int res = 0;
407 
408  res = pthread_mutex_lock( &mMutex );
409  CLAM_ASSERT( res == 0 , "pthread_mutex_lock failed" );
410 
411  bool ret = false;
412 
413  pthread_t tid = pthread_self();
414 
415  if ( mValidID && pthread_equal( mThreadID, tid ) )
416  {
417  ++mCount;
418  ret = true;
419  }
420  else
421  {
422  timespec ts;
423 
424  to_timespec( xt, ts );
425 
426  while( mValidID )
427  {
428  res = pthread_cond_timedwait( &mUnlocked, &mMutex, &ts );
429  if ( res == ETIMEDOUT )
430  break;
431  CLAM_ASSERT( res==0, "pthread_cond_timedwait failed" );
432  }
433 
434  if ( !mValidID )
435  {
436  mThreadID = tid;
437  mValidID = true;
438  mCount = 1;
439  ret = true;
440  }
441  }
442 
443  res = pthread_mutex_unlock( &mMutex );
444  CLAM_ASSERT( res==0, "pthread_mutex_unlock failed" );
445 
446  return ret;
447  }
448 
449  void RecursiveTimedMutex::DoUnlock( )
450  {
451  int res = 0;
452  res = pthread_mutex_lock( &mMutex );
453  CLAM_ASSERT( res == 0, "pthread_mutex_lock failed" );
454 
455  pthread_t tid = pthread_self();
456 
457  if ( mValidID && !pthread_equal( mThreadID, tid ) )
458  {
459  res = pthread_mutex_unlock( &mMutex );
460  CLAM_ASSERT( res == 0, "pthread_mutex_unlock failed" );
461  }
462 
463  if ( --mCount == 0 )
464  {
465  CLAM_ASSERT( mValidID, "Spurious value change!" );
466  mValidID = false;
467 
468  res = pthread_cond_signal( &mUnlocked );
469  CLAM_ASSERT( res == 0, "pthread_cond_signal failed" );
470  }
471 
472  res = pthread_mutex_unlock( &mMutex );
473  CLAM_ASSERT( res == 0, "pthread_mutex_unlock failed" );
474  }
475 
476  void RecursiveTimedMutex::DoLock( ConditionVar& state )
477  {
478  int res = 0;
479 
480  while ( mValidID )
481  {
482  res = pthread_cond_wait( &mUnlocked, &mMutex );
483  CLAM_ASSERT( res == 0, "pthread_cond_wait failed!" );
484  }
485 
486  mThreadID = pthread_self();
487  mValidID = true;
488  mCount = state.count;
489 
490  res = pthread_mutex_unlock( &mMutex );
491  CLAM_ASSERT( res == 0, "pthread_mutex_unlock failed" );
492  }
493 
494  void RecursiveTimedMutex::DoUnlock( ConditionVar& state )
495  {
496  int res = 0;
497 
498  res = pthread_mutex_lock( &mMutex );
499  CLAM_ASSERT( res == 0, "pthread_mutex_lock failed" );
500 
501  CLAM_ASSERT( mValidID, "Spurious value change!" );
502  mValidID = false;
503 
504  res = pthread_cond_signal( &mUnlocked );
505  CLAM_ASSERT( res == 0, "pthread_cond_signal failed!" );
506 
507  state.pmutex = &mMutex;
508  state.count = mCount;
509  }
510 
511 
512 } // end of namespace CLAM
513