CLAM-Development
1.1
|
00001 /* 00002 * Copyright (c) 2004 MUSIC TECHNOLOGY GROUP (MTG) 00003 * UNIVERSITAT POMPEU FABRA 00004 * 00005 * 00006 * This program is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation; either version 2 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software 00018 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 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 } // end of namespace CLAM 00513