00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "RecursiveMutex.hxx"
00023 #include "xtime.hxx"
00024 #include "Assert.hxx"
00025 #include <pthread.h>
00026 #include <errno.h>
00027
00028 namespace CLAM
00029 {
00030
00031
00032 RecursiveMutex::RecursiveMutex()
00033 : mCount(0), mValidID( false )
00034 {
00035 pthread_mutexattr_t attr;
00036
00037 int res = 0;
00038
00039 res = pthread_mutexattr_init( &attr );
00040 CLAM_ASSERT( res == 0, "pthread_mutexattr_init failed" );
00041
00042 res = pthread_mutex_init( &mMutex, &attr );
00043 CLAM_ASSERT( res == 0, "pthread_mutex_init failed");
00044
00045 res = pthread_cond_init( &mUnlocked, 0 );
00046
00047 if ( res!= 0 )
00048 {
00049 pthread_mutex_destroy( &mMutex );
00050 throw ThreadResourceError("pthread_cond_init failed");
00051 }
00052 }
00053
00054 RecursiveMutex::~RecursiveMutex()
00055 {
00056 int res = 0;
00057 res = pthread_mutex_destroy( &mMutex );
00058
00059 CLAM_ASSERT( res == 0, "pthread_mutex_destroy failed" );
00060
00061 res = pthread_cond_destroy( &mUnlocked );
00062
00063 CLAM_ASSERT( res == 0, "pthread_cond_destroy failed" );
00064 }
00065
00066
00067 void RecursiveMutex::DoLock()
00068 {
00069 int res = 0;
00070
00071 res = pthread_mutex_lock( &mMutex );
00072
00073 pthread_t tid = pthread_self();
00074
00075 if ( mValidID && pthread_equal( mThreadID, tid ) )
00076 ++ mCount;
00077 else
00078 {
00079 while ( mValidID )
00080 {
00081 res = pthread_cond_wait( &mUnlocked, &mMutex );
00082 CLAM_ASSERT( res == 0, "pthread_cond_wait failed" );
00083 }
00084
00085 mThreadID = tid;
00086 mValidID = true;
00087 mCount = 1;
00088 }
00089
00090 res = pthread_mutex_unlock( &mMutex );
00091 CLAM_ASSERT( res == 0, "pthread_mutex_unlock failed" );
00092 }
00093
00094 void RecursiveMutex::DoUnlock( )
00095 {
00096 int res = 0;
00097 res = pthread_mutex_lock( &mMutex );
00098 CLAM_ASSERT( res == 0, "pthread_mutex_lock failed" );
00099
00100 pthread_t tid = pthread_self();
00101
00102 if ( mValidID && !pthread_equal( mThreadID, tid ) )
00103 {
00104 res = pthread_mutex_unlock( &mMutex );
00105 CLAM_ASSERT( res == 0, "pthread_mutex_unlock failed" );
00106 }
00107
00108 if ( --mCount == 0 )
00109 {
00110 CLAM_ASSERT( mValidID, "Spurious value change!" );
00111 mValidID = false;
00112
00113 res = pthread_cond_signal( &mUnlocked );
00114 CLAM_ASSERT( res==0, "pthread_cond_signal failed" );
00115 }
00116
00117 res = pthread_mutex_unlock( &mMutex );
00118 CLAM_ASSERT( res == 0, "pthread_mutex_unlock failed" );
00119 }
00120
00121 void RecursiveMutex::DoLock( ConditionVar& state )
00122 {
00123 int res = 0;
00124
00125 while ( mValidID )
00126 {
00127 res = pthread_cond_wait( &mUnlocked, &mMutex );
00128 CLAM_ASSERT( res == 0, "pthread_cond_wait failed!" );
00129 }
00130
00131 mThreadID = pthread_self();
00132 mValidID = true;
00133 mCount = state.count;
00134
00135 res = pthread_mutex_unlock( &mMutex );
00136 CLAM_ASSERT( res == 0, "pthread_mutex_unlock failed" );
00137 }
00138
00139 void RecursiveMutex::DoUnlock( ConditionVar& state )
00140 {
00141 int res = 0;
00142
00143 res = pthread_mutex_lock( &mMutex );
00144 CLAM_ASSERT( res == 0, "pthread_mutex_lock failed" );
00145
00146 CLAM_ASSERT( mValidID, "Spurious value change!" );
00147 mValidID = false;
00148
00149 res = pthread_cond_signal( &mUnlocked );
00150 CLAM_ASSERT( res == 0, "pthread_cond_signal failed!" );
00151
00152 state.pmutex = &mMutex;
00153 state.count = mCount;
00154 }
00155
00156 RecursiveTryMutex::RecursiveTryMutex()
00157 : mCount(0), mValidID( false )
00158 {
00159 pthread_mutexattr_t attr;
00160
00161 int res = 0;
00162
00163 res = pthread_mutexattr_init( &attr );
00164 CLAM_ASSERT( res == 0, "pthread_mutexattr_init failed" );
00165
00166 res = pthread_mutex_init( &mMutex, &attr );
00167 CLAM_ASSERT( res == 0, "pthread_mutex_init failed");
00168
00169 res = pthread_cond_init( &mUnlocked, 0 );
00170
00171 if ( res!= 0 )
00172 {
00173 pthread_mutex_destroy( &mMutex );
00174 throw ThreadResourceError("pthread_cond_init failed");
00175 }
00176 }
00177
00178 RecursiveTryMutex::~RecursiveTryMutex()
00179 {
00180 int res = 0;
00181 res = pthread_mutex_destroy( &mMutex );
00182
00183 CLAM_ASSERT( res == 0, "pthread_mutex_destroy failed" );
00184
00185 res = pthread_cond_destroy( &mUnlocked );
00186
00187 CLAM_ASSERT( res == 0, "pthread_cond_destroy failed" );
00188 }
00189
00190
00191 void RecursiveTryMutex::DoLock()
00192 {
00193 int res = 0;
00194
00195 res = pthread_mutex_lock( &mMutex );
00196
00197 pthread_t tid = pthread_self();
00198
00199 if ( mValidID && pthread_equal( mThreadID, tid ) )
00200 ++ mCount;
00201 else
00202 {
00203 while ( mValidID )
00204 {
00205 res = pthread_cond_wait( &mUnlocked, &mMutex );
00206 CLAM_ASSERT( res == 0, "pthread_cond_wait failed" );
00207 }
00208
00209 mThreadID = tid;
00210 mValidID = true;
00211 mCount = 1;
00212 }
00213
00214 res = pthread_mutex_unlock( &mMutex );
00215 CLAM_ASSERT( res == 0, "pthread_mutex_unlock failed" );
00216 }
00217
00218 bool RecursiveTryMutex::DoTryLock()
00219 {
00220 int res = 0;
00221
00222 res = pthread_mutex_lock( &mMutex );
00223 CLAM_ASSERT( res == 0, " pthread_mutex_lock failed " );
00224
00225 bool ret = false;
00226
00227 pthread_t tid = pthread_self();
00228
00229 if (mValidID && pthread_equal(mThreadID, tid ) )
00230 {
00231 ++mCount;
00232 ret = true;
00233 }
00234 else if ( !mValidID )
00235 {
00236 mThreadID = tid;
00237 mValidID = true;
00238 mCount = 1;
00239 ret = true;
00240 }
00241
00242 res = pthread_mutex_unlock(&mMutex );
00243 CLAM_ASSERT( res==0, "pthread_mutex_unlock failed" );
00244
00245 return ret;
00246 }
00247
00248 void RecursiveTryMutex::DoUnlock( )
00249 {
00250 int res = 0;
00251 res = pthread_mutex_lock( &mMutex );
00252 CLAM_ASSERT( res == 0, "pthread_mutex_lock failed" );
00253
00254 pthread_t tid = pthread_self();
00255
00256 if ( mValidID && !pthread_equal( mThreadID, tid ) )
00257 {
00258 res = pthread_mutex_unlock( &mMutex );
00259 CLAM_ASSERT( res == 0, "pthread_mutex_unlock failed" );
00260 }
00261
00262 if ( --mCount == 0 )
00263 {
00264 CLAM_ASSERT( mValidID, "Spurious value change!" );
00265 mValidID = false;
00266
00267 res = pthread_cond_signal( &mUnlocked );
00268 CLAM_ASSERT( res==0, "pthread_cond_signal failed" );
00269 }
00270
00271 res = pthread_mutex_unlock( &mMutex );
00272 CLAM_ASSERT( res == 0, "pthread_mutex_unlock failed" );
00273 }
00274
00275 void RecursiveTryMutex::DoLock( ConditionVar& state )
00276 {
00277 int res = 0;
00278
00279 while ( mValidID )
00280 {
00281 res = pthread_cond_wait( &mUnlocked, &mMutex );
00282 CLAM_ASSERT( res == 0, "pthread_cond_wait failed!" );
00283 }
00284
00285 mThreadID = pthread_self();
00286 mValidID = true;
00287 mCount = state.count;
00288
00289 res = pthread_mutex_unlock( &mMutex );
00290 CLAM_ASSERT( res == 0, "pthread_mutex_unlock failed" );
00291 }
00292
00293 void RecursiveTryMutex::DoUnlock( ConditionVar& state )
00294 {
00295 int res = 0;
00296
00297 res = pthread_mutex_lock( &mMutex );
00298 CLAM_ASSERT( res == 0, "pthread_mutex_lock failed" );
00299
00300 CLAM_ASSERT( mValidID, "Spurious value change!" );
00301 mValidID = false;
00302
00303 res = pthread_cond_signal( &mUnlocked );
00304 CLAM_ASSERT( res == 0, "pthread_cond_signal failed!" );
00305
00306 state.pmutex = &mMutex;
00307 state.count = mCount;
00308 }
00309
00310
00311 RecursiveTimedMutex::RecursiveTimedMutex()
00312 : mCount(0), mValidID( false )
00313 {
00314 pthread_mutexattr_t attr;
00315
00316 int res = 0;
00317
00318 res = pthread_mutexattr_init( &attr );
00319 CLAM_ASSERT( res == 0, "pthread_mutexattr_init failed" );
00320
00321
00322 res = pthread_mutex_init( &mMutex, &attr );
00323 CLAM_ASSERT( res == 0, "pthread_mutex_init failed");
00324
00325 res = pthread_cond_init( &mUnlocked, 0 );
00326
00327 if ( res!= 0 )
00328 {
00329 pthread_mutex_destroy( &mMutex );
00330 throw ThreadResourceError("pthread_cond_init failed");
00331 }
00332 }
00333
00334 RecursiveTimedMutex::~RecursiveTimedMutex()
00335 {
00336 int res = 0;
00337 res = pthread_mutex_destroy( &mMutex );
00338
00339 CLAM_ASSERT( res == 0, "pthread_mutex_destroy failed" );
00340
00341 res = pthread_cond_destroy( &mUnlocked );
00342
00343 CLAM_ASSERT( res == 0, "pthread_cond_destroy failed" );
00344 }
00345
00346
00347 void RecursiveTimedMutex::DoLock()
00348 {
00349 int res = 0;
00350
00351 res = pthread_mutex_lock( &mMutex );
00352
00353 pthread_t tid = pthread_self();
00354
00355 if ( mValidID && pthread_equal( mThreadID, tid ) )
00356 ++ mCount;
00357 else
00358 {
00359 while ( mValidID )
00360 {
00361 res = pthread_cond_wait( &mUnlocked, &mMutex );
00362 CLAM_ASSERT( res == 0, "pthread_cond_wait failed" );
00363 }
00364
00365 mThreadID = tid;
00366 mValidID = true;
00367 mCount = 1;
00368 }
00369
00370 res = pthread_mutex_unlock( &mMutex );
00371 CLAM_ASSERT( res == 0, "pthread_mutex_unlock failed" );
00372 }
00373
00374 bool RecursiveTimedMutex::DoTryLock()
00375 {
00376 int res = 0;
00377
00378 res = pthread_mutex_lock( &mMutex );
00379 CLAM_ASSERT( res == 0, " pthread_mutex_lock failed " );
00380
00381 bool ret = false;
00382
00383 pthread_t tid = pthread_self();
00384
00385 if (mValidID && pthread_equal(mThreadID, tid ) )
00386 {
00387 ++mCount;
00388 ret = true;
00389 }
00390 else if ( !mValidID )
00391 {
00392 mThreadID = tid;
00393 mValidID = true;
00394 mCount = 1;
00395 ret = true;
00396 }
00397
00398 res = pthread_mutex_unlock(&mMutex );
00399 CLAM_ASSERT( res==0, "pthread_mutex_unlock failed" );
00400
00401 return ret;
00402 }
00403
00404 bool RecursiveTimedMutex::DoTimedLock( const xtime& xt )
00405 {
00406 int res = 0;
00407
00408 res = pthread_mutex_lock( &mMutex );
00409 CLAM_ASSERT( res == 0 , "pthread_mutex_lock failed" );
00410
00411 bool ret = false;
00412
00413 pthread_t tid = pthread_self();
00414
00415 if ( mValidID && pthread_equal( mThreadID, tid ) )
00416 {
00417 ++mCount;
00418 ret = true;
00419 }
00420 else
00421 {
00422 timespec ts;
00423
00424 to_timespec( xt, ts );
00425
00426 while( mValidID )
00427 {
00428 res = pthread_cond_timedwait( &mUnlocked, &mMutex, &ts );
00429 if ( res == ETIMEDOUT )
00430 break;
00431 CLAM_ASSERT( res==0, "pthread_cond_timedwait failed" );
00432 }
00433
00434 if ( !mValidID )
00435 {
00436 mThreadID = tid;
00437 mValidID = true;
00438 mCount = 1;
00439 ret = true;
00440 }
00441 }
00442
00443 res = pthread_mutex_unlock( &mMutex );
00444 CLAM_ASSERT( res==0, "pthread_mutex_unlock failed" );
00445
00446 return ret;
00447 }
00448
00449 void RecursiveTimedMutex::DoUnlock( )
00450 {
00451 int res = 0;
00452 res = pthread_mutex_lock( &mMutex );
00453 CLAM_ASSERT( res == 0, "pthread_mutex_lock failed" );
00454
00455 pthread_t tid = pthread_self();
00456
00457 if ( mValidID && !pthread_equal( mThreadID, tid ) )
00458 {
00459 res = pthread_mutex_unlock( &mMutex );
00460 CLAM_ASSERT( res == 0, "pthread_mutex_unlock failed" );
00461 }
00462
00463 if ( --mCount == 0 )
00464 {
00465 CLAM_ASSERT( mValidID, "Spurious value change!" );
00466 mValidID = false;
00467
00468 res = pthread_cond_signal( &mUnlocked );
00469 CLAM_ASSERT( res == 0, "pthread_cond_signal failed" );
00470 }
00471
00472 res = pthread_mutex_unlock( &mMutex );
00473 CLAM_ASSERT( res == 0, "pthread_mutex_unlock failed" );
00474 }
00475
00476 void RecursiveTimedMutex::DoLock( ConditionVar& state )
00477 {
00478 int res = 0;
00479
00480 while ( mValidID )
00481 {
00482 res = pthread_cond_wait( &mUnlocked, &mMutex );
00483 CLAM_ASSERT( res == 0, "pthread_cond_wait failed!" );
00484 }
00485
00486 mThreadID = pthread_self();
00487 mValidID = true;
00488 mCount = state.count;
00489
00490 res = pthread_mutex_unlock( &mMutex );
00491 CLAM_ASSERT( res == 0, "pthread_mutex_unlock failed" );
00492 }
00493
00494 void RecursiveTimedMutex::DoUnlock( ConditionVar& state )
00495 {
00496 int res = 0;
00497
00498 res = pthread_mutex_lock( &mMutex );
00499 CLAM_ASSERT( res == 0, "pthread_mutex_lock failed" );
00500
00501 CLAM_ASSERT( mValidID, "Spurious value change!" );
00502 mValidID = false;
00503
00504 res = pthread_cond_signal( &mUnlocked );
00505 CLAM_ASSERT( res == 0, "pthread_cond_signal failed!" );
00506
00507 state.pmutex = &mMutex;
00508 state.count = mCount;
00509 }
00510
00511
00512 }
00513