00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00018 #ifndef LIBCWD_PRIVATE_THREADING_H
00019 #define LIBCWD_PRIVATE_THREADING_H
00020
00021 #define LIBCWD_DEBUGDEBUGRWLOCK 0
00022
00023 #if LIBCWD_DEBUGDEBUGRWLOCK
00024 #define LIBCWD_NO_INTERNAL_STRING
00025 #include <raw_write.h>
00026 #undef LIBCWD_NO_INTERNAL_STRING
00027 extern pthread_mutex_t LIBCWD_DEBUGDEBUGLOCK_CERR_mutex;
00028 extern unsigned int LIBCWD_DEBUGDEBUGLOCK_CERR_count;
00029 #define LIBCWD_DEBUGDEBUGRWLOCK_CERR(x) \
00030 do { \
00031 pthread_mutex_lock(&LIBCWD_DEBUGDEBUGLOCK_CERR_mutex); \
00032 FATALDEBUGDEBUG_CERR(x); \
00033 pthread_mutex_unlock(&LIBCWD_DEBUGDEBUGLOCK_CERR_mutex); \
00034 } while(0)
00035 #define LIBCWD_DEBUGDEBUGLOCK_CERR(x) \
00036 do { \
00037 if (instance != static_tsd_instance) \
00038 { \
00039 pthread_mutex_lock(&LIBCWD_DEBUGDEBUGLOCK_CERR_mutex); \
00040 ++LIBCWD_DEBUGDEBUGLOCK_CERR_count; \
00041 FATALDEBUGDEBUG_CERR("[" << LIBCWD_DEBUGDEBUGLOCK_CERR_count << "] " << pthread_self() << ": " << x); \
00042 pthread_mutex_unlock(&LIBCWD_DEBUGDEBUGLOCK_CERR_mutex); \
00043 } \
00044 } while(0)
00045 #else // !LIBCWD_DEBUGDEBUGRWLOCK
00046 #define LIBCWD_DEBUGDEBUGRWLOCK_CERR(x) do { } while(0)
00047 #define LIBCWD_DEBUGDEBUGLOCK_CERR(x) do { } while(0)
00048 #endif // !LIBCWD_DEBUGDEBUGRWLOCK
00049
00050 #ifndef LIBCWD_PRIVATE_SET_ALLOC_CHECKING_H
00051 #include <libcwd/private_set_alloc_checking.h>
00052 #endif
00053 #ifndef LIBCWD_PRIVATE_STRUCT_TSD_H
00054 #include <libcwd/private_struct_TSD.h>
00055 #endif
00056 #ifndef LIBCWD_PRIVATE_MUTEX_INSTANCES_H
00057 #include <libcwd/private_mutex_instances.h>
00058 #endif
00059 #ifndef LIBCWD_CORE_DUMP_H
00060 #include <libcwd/core_dump.h>
00061 #endif
00062 #ifndef LIBCW_CSTRING
00063 #define LIBCW_CSTRING
00064 #include <cstring>
00065 #endif
00066
00067 #ifdef LIBCWD_HAVE_PTHREAD
00068 #ifdef __linux
00069 #ifndef _GNU_SOURCE
00070 #error "You need to use define _GNU_SOURCE in order to make use of the extensions of Linux Threads."
00071 #endif
00072 #endif
00073 #ifndef LIBCW_PTHREAD_H
00074 #define LIBCW_PTHREAD_H
00075 #include <pthread.h>
00076 #endif
00077 #if defined(PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP) && defined(PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP)
00078 #define LIBCWD_USE_LINUXTHREADS 1
00079 #else
00080 #define LIBCWD_USE_POSIX_THREADS 1
00081 #endif
00082 #else
00083 #if LIBCWD_THREAD_SAFE
00084 #error Fatal error: thread support was not detected during configuration of libcwd (did you use --disable-threading?)! \
00085 How come you are trying to compile a threaded program now? \
00086 To fix this problem, either link with libcwd_r (install it), or when you are indeed compiling a \
00087 single threaded application, then get rid of the -D_REENTRANT and/or -D_THREAD_SAFE in your compile flags.
00088 #endif
00089 #endif // LIBCWD_HAVE_PTHREAD
00090
00091 #ifndef LIBCWD_USE_LINUXTHREADS
00092 #define LIBCWD_USE_LINUXTHREADS 0
00093 #endif
00094 #ifndef LIBCWD_USE_POSIX_THREADS
00095 #define LIBCWD_USE_POSIX_THREADS 0
00096 #endif
00097
00098 #if CWDEBUG_DEBUGT
00099 #define LibcwDebugThreads(x) do { x; } while(0)
00100 #else
00101 #define LibcwDebugThreads(x) do { } while(0)
00102 #endif
00103
00104 #if CWDEBUG_DEBUGT || CWDEBUG_DEBUG
00105 #ifndef LIBCWD_PRIVATE_ASSERT_H
00106 #include <libcwd/private_assert.h>
00107 #endif
00108 #endif
00109
00110 #if LIBCWD_THREAD_SAFE
00111
00112 namespace libcwd {
00113
00114 #if LIBCWD_DEBUGDEBUGRWLOCK
00115 inline
00116 _private_::raw_write_nt const&
00117 operator<<(_private_::raw_write_nt const& raw_write, pthread_mutex_t const& mutex)
00118 {
00119 raw_write << "(pthread_mutex_t&)" << (void*)&mutex <<
00120 " = { __m_reserved = " << mutex.__m_reserved <<
00121 ", __m_count = " << mutex.__m_count <<
00122 ", __m_owner = " << (void*)mutex.__m_owner <<
00123 ", __m_kind = " << mutex.__m_kind <<
00124 ", __m_lock = { __status = " << mutex.__m_lock.__status <<
00125 ", __spinlock = " << mutex.__m_lock.__spinlock << " } }";
00126 return raw_write;
00127 }
00128 #endif
00129
00130 namespace _private_ {
00131
00132 extern void initialize_global_mutexes(void);
00133 extern bool WST_multi_threaded;
00134
00135 #if CWDEBUG_DEBUGT
00136 extern void test_for_deadlock(int, struct TSD_st&, void const*);
00137 inline void test_for_deadlock(void const* ptr, struct TSD_st& __libcwd_tsd, void const* from)
00138 {
00139 test_for_deadlock(reinterpret_cast<int>(ptr), __libcwd_tsd, from);
00140 }
00141 #endif
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164 #if LIBCWD_USE_POSIX_THREADS || LIBCWD_USE_LINUXTHREADS
00165
00166
00167 #define LIBCWD_DISABLE_CANCEL \
00168 { \
00169 LIBCWD_DISABLE_CANCEL_NO_BRACE
00170 #define LIBCWD_DISABLE_CANCEL_NO_BRACE \
00171 int __libcwd_oldstate; \
00172 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &__libcwd_oldstate); \
00173 LibcwDebugThreads( ++__libcwd_tsd.cancel_explicitely_disabled )
00174 #if CWDEBUG_ALLOC
00175 #define LIBCWD_ASSERT_USERSPACE_OR_DEFERED_BEFORE_SETCANCELSTATE \
00176 \
00177 \
00178 \
00179 \
00180 LIBCWD_ASSERT( !__libcwd_tsd.internal || __libcwd_tsd.cancel_explicitely_disabled || __libcwd_tsd.cancel_explicitely_deferred )
00181 #else
00182 #define LIBCWD_ASSERT_USERSPACE_OR_DEFERED_BEFORE_SETCANCELSTATE
00183 #endif
00184 #define LIBCWD_ENABLE_CANCEL_NO_BRACE \
00185 LibcwDebugThreads(\
00186 LIBCWD_ASSERT( __libcwd_tsd.cancel_explicitely_disabled > 0 ); \
00187 --__libcwd_tsd.cancel_explicitely_disabled; \
00188 LIBCWD_ASSERT_USERSPACE_OR_DEFERED_BEFORE_SETCANCELSTATE; \
00189 ); \
00190 pthread_setcancelstate(__libcwd_oldstate, NULL)
00191 #define LIBCWD_ENABLE_CANCEL \
00192 LIBCWD_ENABLE_CANCEL_NO_BRACE; \
00193 }
00194
00195 #define LIBCWD_DEFER_CANCEL \
00196 { \
00197 LIBCWD_DEFER_CANCEL_NO_BRACE
00198 #define LIBCWD_DEFER_CANCEL_NO_BRACE \
00199 int __libcwd_oldtype; \
00200 pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &__libcwd_oldtype); \
00201 LibcwDebugThreads( ++__libcwd_tsd.cancel_explicitely_deferred )
00202 #define LIBCWD_RESTORE_CANCEL_NO_BRACE \
00203 LibcwDebugThreads(\
00204 LIBCWD_ASSERT( __libcwd_tsd.cancel_explicitely_deferred > 0 ); \
00205 --__libcwd_tsd.cancel_explicitely_deferred; \
00206 LIBCWD_ASSERT_USERSPACE_OR_DEFERED_BEFORE_SETCANCELSTATE; \
00207 ); \
00208 pthread_setcanceltype(__libcwd_oldtype, NULL)
00209 #define LIBCWD_RESTORE_CANCEL \
00210 LIBCWD_RESTORE_CANCEL_NO_BRACE; \
00211 }
00212
00213 #if LIBCWD_USE_LINUXTHREADS
00214 #define LIBCWD_DEFER_CLEANUP_PUSH(routine, arg) \
00215 pthread_cleanup_push_defer_np(reinterpret_cast<void(*)(void*)>(routine), reinterpret_cast<void*>(arg)); \
00216 LibcwDebugThreads( ++__libcwd_tsd.cancel_explicitely_deferred; ++__libcwd_tsd.cleanup_handler_installed )
00217 #if CWDEBUG_ALLOC
00218 #define LIBCWD_ASSERT_NONINTERNAL LIBCWD_ASSERT( !__libcwd_tsd.internal )
00219 #else
00220 #define LIBCWD_ASSERT_NONINTERNAL
00221 #endif
00222 #define LIBCWD_CLEANUP_POP_RESTORE(execute) \
00223 LibcwDebugThreads( --__libcwd_tsd.cleanup_handler_installed; \
00224 LIBCWD_ASSERT( __libcwd_tsd.cancel_explicitely_deferred > 0 ); \
00225 LIBCWD_ASSERT_NONINTERNAL; ); \
00226 pthread_cleanup_pop_restore_np(static_cast<int>(execute)); \
00227 LibcwDebugThreads( --__libcwd_tsd.cancel_explicitely_deferred; )
00228 #else // !LIBCWD_USE_LINUXTHREADS
00229 #define LIBCWD_DEFER_CLEANUP_PUSH(routine, arg) \
00230 LIBCWD_DEFER_CANCEL; \
00231 LibcwDebugThreads( ++__libcwd_tsd.cleanup_handler_installed ); \
00232 pthread_cleanup_push(reinterpret_cast<void(*)(void*)>(routine), reinterpret_cast<void*>(arg))
00233 #define LIBCWD_CLEANUP_POP_RESTORE(execute) \
00234 LibcwDebugThreads( --__libcwd_tsd.cleanup_handler_installed ); \
00235 pthread_cleanup_pop(static_cast<int>(execute)); \
00236 LIBCWD_RESTORE_CANCEL
00237 #endif // !LIBCWD_USE_LINUXTHREADS
00238
00239 #define LIBCWD_PUSH_DEFER_TRYLOCK_MUTEX(instance, unlock_routine) \
00240 LIBCWD_DEFER_CLEANUP_PUSH(static_cast<void (*)(void)>(unlock_routine), &::libcwd::_private_::mutex_tct<(instance)>::S_mutex); \
00241 bool __libcwd_lock_successful = ::libcwd::_private_::mutex_tct<(instance)>::trylock()
00242 #define LIBCWD_DEFER_PUSH_LOCKMUTEX(instance, unlock_routine) \
00243 LIBCWD_DEFER_CLEANUP_PUSH(static_cast<void (*)(void)>(unlock_routine), &::libcwd::_private_::mutex_tct<(instance)>::S_mutex); \
00244 ::libcwd::_private_::mutex_tct<(instance)>::lock(); \
00245 bool const __libcwd_lock_successful = true
00246 #define LIBCWD_UNLOCKMUTEX_POP_RESTORE(instance) \
00247 LIBCWD_CLEANUP_POP_RESTORE(__libcwd_lock_successful)
00248
00249 #define LIBCWD_DEBUGDEBUG_ASSERT_CANCEL_DEFERRED \
00250 LibcwDebugThreads( \
00251 if (instance != static_tsd_instance) \
00252 { \
00253 \
00254 \
00255 \
00256 LIBCWD_ASSERT( __libcwd_tsd.cancel_explicitely_deferred || __libcwd_tsd.cancel_explicitely_disabled ); \
00257 } )
00258
00259 template <int instance>
00260 class mutex_tct {
00261 public:
00262 static pthread_mutex_t S_mutex;
00263 #if !LIBCWD_USE_LINUXTHREADS || CWDEBUG_DEBUGT
00264 protected:
00265 static bool volatile S_initialized;
00266 static void S_initialize(void);
00267 #endif
00268 public:
00269 static void initialize(void)
00270 #if LIBCWD_USE_LINUXTHREADS && !CWDEBUG_DEBUGT
00271 { }
00272 #else
00273 {
00274 if (S_initialized)
00275 return;
00276
00277 S_initialize();
00278 }
00279 #endif
00280 public:
00281 static bool trylock(void)
00282 {
00283 LibcwDebugThreads( LIBCWD_ASSERT( S_initialized ) );
00284 #if CWDEBUG_DEBUGT
00285 LIBCWD_TSD_DECLARATION;
00286 #endif
00287 LIBCWD_DEBUGDEBUG_ASSERT_CANCEL_DEFERRED;
00288 LIBCWD_DEBUGDEBUGLOCK_CERR("Trying to lock mutex " << instance << " (" << (void*)&S_mutex << ") from " << __builtin_return_address(0) << " from " << __builtin_return_address(1));
00289 LIBCWD_DEBUGDEBUGLOCK_CERR("pthread_mutex_trylock(" << S_mutex << ").");
00290 bool success = (pthread_mutex_trylock(&S_mutex) == 0);
00291 LIBCWD_DEBUGDEBUGLOCK_CERR("Result = " << success << ". Mutex now " << S_mutex << ".");
00292 #if CWDEBUG_DEBUG || CWDEBUG_DEBUGT
00293 if (success)
00294 {
00295 #if CWDEBUG_DEBUGT
00296 _private_::test_for_deadlock(instance, __libcwd_tsd, __builtin_return_address(0));
00297 #endif
00298 LIBCWD_DEBUGDEBUGLOCK_CERR("mutex_tct::trylock(): instance_locked[" << instance << "] == " << instance_locked[instance] << "; incrementing it.");
00299 instance_locked[instance] += 1;
00300 #if CWDEBUG_DEBUGT
00301 locked_by[instance] = pthread_self();
00302 locked_from[instance] = __builtin_return_address(0);
00303 #endif
00304 }
00305 #endif
00306 LibcwDebugThreads( if (success) { ++__libcwd_tsd.inside_critical_area; } );
00307 return success;
00308 }
00309 static void lock(void)
00310 {
00311 LibcwDebugThreads( LIBCWD_ASSERT( S_initialized ) );
00312 #if CWDEBUG_DEBUGT
00313 TSD_st* tsd_ptr = 0;
00314 if (instance != static_tsd_instance)
00315 {
00316 LIBCWD_TSD_DECLARATION;
00317 tsd_ptr = &__libcwd_tsd;
00318 }
00319 TSD_st& __libcwd_tsd(*tsd_ptr);
00320 #endif
00321 LIBCWD_DEBUGDEBUG_ASSERT_CANCEL_DEFERRED;
00322 LibcwDebugThreads( if (instance != static_tsd_instance) { ++__libcwd_tsd.inside_critical_area; } );
00323 LIBCWD_DEBUGDEBUGLOCK_CERR("locking mutex " << instance << " (" << (void*)&S_mutex << ") from " << __builtin_return_address(0) << " from " << __builtin_return_address(1));
00324 #if CWDEBUG_DEBUGT
00325 if (instance != static_tsd_instance && !(instance >= 2 * reserved_instance_low && instance < 3 * reserved_instance_low))
00326 {
00327 __libcwd_tsd.waiting_for_lock = instance;
00328 LIBCWD_DEBUGDEBUGLOCK_CERR("pthread_mutex_lock(" << S_mutex << ").");
00329 int res = pthread_mutex_lock(&S_mutex);
00330 LIBCWD_DEBUGDEBUGLOCK_CERR("Result = " << res << ". Mutex now " << S_mutex << ".");
00331 LIBCWD_ASSERT( res == 0 );
00332 __libcwd_tsd.waiting_for_lock = 0;
00333 _private_::test_for_deadlock(instance, __libcwd_tsd, __builtin_return_address(0));
00334 }
00335 else
00336 {
00337 LIBCWD_DEBUGDEBUGLOCK_CERR("pthread_mutex_lock(" << S_mutex << ").");
00338 int res = pthread_mutex_lock(&S_mutex);
00339 LIBCWD_DEBUGDEBUGLOCK_CERR("Result = " << res << ". Mutex now " << S_mutex << ".");
00340 LIBCWD_ASSERT( res == 0 );
00341 }
00342 #else // !CWDEBUG_DEBUGT
00343 pthread_mutex_lock(&S_mutex);
00344 #endif // !CWDEBUG_DEBUGT
00345 LIBCWD_DEBUGDEBUGLOCK_CERR("Lock " << instance << " obtained (" << (void*)&S_mutex << ").");
00346 #if CWDEBUG_DEBUG || CWDEBUG_DEBUGT
00347 LIBCWD_DEBUGDEBUGLOCK_CERR("mutex_tct::lock(): instance_locked[" << instance << "] == " << instance_locked[instance] << "; incrementing it.");
00348 instance_locked[instance] += 1;
00349 #if CWDEBUG_DEBUGT
00350 if (locked_by[instance] != 0 && locked_by[instance] != pthread_self())
00351 {
00352 LIBCWD_DEBUGDEBUGLOCK_CERR("mutex " << instance << " (" << (void*)&S_mutex << ") is already set by another thread (" << locked_by[instance] << ")!");
00353 core_dump();
00354 }
00355 locked_by[instance] = pthread_self();
00356 locked_from[instance] = __builtin_return_address(0);
00357 #endif
00358 #endif
00359 }
00360 static void unlock(void)
00361 {
00362 #if CWDEBUG_DEBUGT
00363 TSD_st* tsd_ptr = 0;
00364 if (instance != static_tsd_instance)
00365 {
00366 LIBCWD_TSD_DECLARATION;
00367 tsd_ptr = &__libcwd_tsd;
00368 }
00369 TSD_st& __libcwd_tsd(*tsd_ptr);
00370 #endif
00371 LIBCWD_DEBUGDEBUG_ASSERT_CANCEL_DEFERRED;
00372 #if CWDEBUG_DEBUG || CWDEBUG_DEBUGT
00373 LIBCWD_DEBUGDEBUGLOCK_CERR("mutex_tct::unlock(): instance_locked[" << instance << "] == " << instance_locked[instance] << "; decrementing it.");
00374 LIBCWD_ASSERT( instance_locked[instance] > 0 );
00375 #if CWDEBUG_DEBUGT
00376 if (locked_by[instance] != pthread_self())
00377 {
00378 LIBCWD_DEBUGDEBUGLOCK_CERR("unlocking instance " << instance << " (" << (void*)&S_mutex << ") failed: locked_by[" << instance << "] == " << locked_by[instance] << ".");
00379 core_dump();
00380 }
00381 #endif
00382 instance_locked[instance] -= 1;
00383 #if CWDEBUG_DEBUGT
00384 if (instance_locked[instance] == 0)
00385 {
00386 locked_by[instance] = 0;
00387 LIBCWD_DEBUGDEBUGLOCK_CERR("mutex_tct::unlock(): locked_by[" << instance << "] was reset.");
00388 }
00389 else LIBCWD_DEBUGDEBUGLOCK_CERR("mutex_tct::unlock(): locked_by[" << instance << "] was not reset, it still is " << locked_by[instance] << ".");
00390 #endif
00391 #endif
00392 LIBCWD_DEBUGDEBUGLOCK_CERR("unlocking mutex " << instance << " (" << (void*)&S_mutex << ").");
00393 LIBCWD_DEBUGDEBUGLOCK_CERR("pthread_mutex_unlock(" << S_mutex << ").");
00394 #if CWDEBUG_DEBUGT
00395 int res =
00396 #endif
00397 pthread_mutex_unlock(&S_mutex);
00398 #if CWDEBUG_DEBUGT
00399 LIBCWD_DEBUGDEBUGLOCK_CERR("Result = " << res << ". Mutex now " << S_mutex << ".");
00400 LIBCWD_ASSERT(res == 0);
00401 #endif
00402 LIBCWD_DEBUGDEBUGLOCK_CERR("Lock " << instance << " released (" << (void*)&S_mutex << ").");
00403 LibcwDebugThreads( if (instance != static_tsd_instance) { --__libcwd_tsd.inside_critical_area; } );
00404 }
00405
00406 static void cleanup(void*);
00407 };
00408
00409 #if !LIBCWD_USE_LINUXTHREADS || CWDEBUG_DEBUGT
00410 template <int instance>
00411 bool volatile mutex_tct<instance>::S_initialized = false;
00412
00413 template <int instance>
00414 void mutex_tct<instance>::S_initialize(void)
00415 {
00416 if (instance == mutex_initialization_instance)
00417 {
00418 #if !LIBCWD_USE_LINUXTHREADS
00419 pthread_mutexattr_t mutex_attr;
00420 #if CWDEBUG_DEBUGT
00421 pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_ERRORCHECK);
00422 #else
00423 pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_NORMAL);
00424 #endif
00425 pthread_mutex_init(&S_mutex, &mutex_attr);
00426 #endif // !LIBCWD_USE_LINUXTHREADS
00427 S_initialized = true;
00428 }
00429 else
00430 {
00431 mutex_tct<mutex_initialization_instance>::initialize();
00432
00433 if (!S_initialized)
00434 {
00435 #if !LIBCWD_USE_LINUXTHREADS
00436 pthread_mutexattr_t mutex_attr;
00437 if (instance < end_recursive_types)
00438 pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE);
00439 else
00440 {
00441 #if CWDEBUG_DEBUGT
00442 pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_ERRORCHECK);
00443 #else
00444 pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_NORMAL);
00445 #endif
00446 }
00447 pthread_mutex_init(&S_mutex, &mutex_attr);
00448 #endif // !LIBCWD_USE_LINUXTHREADS
00449 S_initialized = true;
00450 }
00451
00452 }
00453 }
00454 #endif // !LIBCWD_USE_LINUXTHREADS || CWDEBUG_DEBUGT
00455
00456 template <int instance>
00457 pthread_mutex_t mutex_tct<instance>::S_mutex
00458 #if LIBCWD_USE_LINUXTHREADS
00459 =
00460 #if CWDEBUG_DEBUGT
00461 PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
00462 #else
00463 PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP;
00464 #endif
00465 #else // !LIBCWD_USE_LINUXTHREADS
00466 ;
00467 #endif // !LIBCWD_USE_LINUXTHREADS
00468
00469 template <int instance>
00470 void mutex_tct<instance>::cleanup(void*)
00471 {
00472 unlock();
00473 }
00474
00475
00476
00477
00478 template <int instance>
00479 class cond_tct : public mutex_tct<instance> {
00480 private:
00481 static pthread_cond_t S_condition;
00482 #if CWDEBUG_DEBUGT || !LIBCWD_USE_LINUXTHREADS
00483 static bool volatile S_initialized;
00484 private:
00485 static void S_initialize(void);
00486 #endif
00487 public:
00488 static void initialize(void)
00489 #if CWDEBUG_DEBUGT || !LIBCWD_USE_LINUXTHREADS
00490 {
00491 if (S_initialized)
00492 return;
00493 S_initialize();
00494 }
00495 #else
00496 { }
00497 #endif
00498 public:
00499 void wait(void) {
00500 #if CWDEBUG_DEBUG || CWDEBUG_DEBUGT
00501 LIBCWD_DEBUGDEBUGLOCK_CERR("cond_tct::wait(): instance_locked[" << instance << "] == " << instance_locked[instance] << "; decrementing it.");
00502 LIBCWD_ASSERT( instance_locked[instance] > 0 );
00503 #if CWDEBUG_DEBUGT
00504 if (locked_by[instance] != pthread_self())
00505 {
00506 LIBCWD_DEBUGDEBUGLOCK_CERR("unlocking instance " << instance << " (" << (void*)&S_mutex << ") failed: locked_by[" << instance << "] == " << locked_by[instance] << ".");
00507 core_dump();
00508 }
00509 #endif
00510 instance_locked[instance] -= 1;
00511 #if CWDEBUG_DEBUGT
00512 if (instance_locked[instance] == 0)
00513 {
00514 locked_by[instance] = 0;
00515 LIBCWD_DEBUGDEBUGLOCK_CERR("cond_tct::wait(): locked_by[" << instance << "] was reset.");
00516 }
00517 else LIBCWD_DEBUGDEBUGLOCK_CERR("cond_tct::wait(): locked_by[" << instance << "] was not reset, it still is " << locked_by[instance] << ".");
00518 #endif
00519 #endif
00520 LIBCWD_DEBUGDEBUGLOCK_CERR("unlocking mutex " << instance << " (" << (void*)&S_mutex << ").");
00521 LIBCWD_DEBUGDEBUGLOCK_CERR("pthread_cond_wait(" << (void*)&S_condition << ", " << this->S_mutex << ").");
00522 #if CWDEBUG_DEBUGT
00523 int res =
00524 #endif
00525 pthread_cond_wait(&S_condition, &this->S_mutex);
00526 #if CWDEBUG_DEBUGT
00527 LIBCWD_DEBUGDEBUGLOCK_CERR("Result = " << res << ". Mutex now " << S_mutex << ".");
00528 LIBCWD_ASSERT(res == 0);
00529 #endif
00530 LIBCWD_DEBUGDEBUGLOCK_CERR("Lock " << instance << " obtained (" << (void*)&S_mutex << ").");
00531 #if CWDEBUG_DEBUG || CWDEBUG_DEBUGT
00532 LIBCWD_DEBUGDEBUGLOCK_CERR("cond_tct::wait(): instance_locked[" << instance << "] == " << instance_locked[instance] << "; incrementing it.");
00533 instance_locked[instance] += 1;
00534 #if CWDEBUG_DEBUGT
00535 if (locked_by[instance] != 0 && locked_by[instance] != pthread_self())
00536 {
00537 LIBCWD_DEBUGDEBUGLOCK_CERR("mutex " << instance << " (" << (void*)&S_mutex << ") is already set by another thread (" << locked_by[instance] << ")!");
00538 core_dump();
00539 }
00540 locked_by[instance] = pthread_self();
00541 locked_from[instance] = __builtin_return_address(0);
00542 #endif
00543 #endif
00544 }
00545 void signal(void) { pthread_cond_signal(&S_condition); }
00546 void broadcast(void) { pthread_cond_broadcast(&S_condition); }
00547 };
00548
00549 #if CWDEBUG_DEBUGT || !LIBCWD_USE_LINUXTHREADS
00550 template <int instance>
00551 void cond_tct<instance>::S_initialize(void)
00552 {
00553 #if !LIBCWD_USE_LINUXTHREADS
00554 mutex_tct<mutex_initialization_instance>::initialize();
00555 LIBCWD_DEFER_PUSH_LOCKMUTEX(mutex_initialization_instance, mutex_tct<mutex_initialization_instance>::unlock);
00556 if (!S_initialized)
00557 {
00558 pthread_cond_init(&S_condition, NULL);
00559 }
00560 LIBCWD_UNLOCKMUTEX_POP_RESTORE(mutex_initialization_instance);
00561 #endif
00562 mutex_tct<instance>::S_initialize();
00563 }
00564 #endif // !LIBCWD_USE_LINUXTHREADS
00565
00566 #if CWDEBUG_DEBUGT || !LIBCWD_USE_LINUXTHREADS
00567 template <int instance>
00568 bool volatile cond_tct<instance>::S_initialized = false;
00569 #endif
00570
00571 template <int instance>
00572 pthread_cond_t cond_tct<instance>::S_condition
00573 #if LIBCWD_USE_LINUXTHREADS
00574 = PTHREAD_COND_INITIALIZER;
00575 #else // !LIBCWD_USE_LINUXTHREADS
00576 ;
00577 #endif // !LIBCWD_USE_LINUXTHREADS
00578
00579 #endif // LIBCWD_USE_POSIX_THREADS || LIBCWD_USE_LINUXTHREADS
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604 template <int instance>
00605 class rwlock_tct {
00606 private:
00607 static int const readers_instance = instance + reserved_instance_low;
00608 static int const holders_instance = instance + 2 * reserved_instance_low;
00609 typedef cond_tct<holders_instance> cond_t;
00610 static cond_t S_no_holders_condition;
00611 static int S_holders_count;
00612 static bool volatile S_writer_is_waiting;
00613 static pthread_t S_writer_id;
00614 #if CWDEBUG_DEBUGT || !LIBCWD_USE_LINUXTHREADS
00615 static bool S_initialized;
00616 #endif
00617 public:
00618 static void initialize(void)
00619 {
00620 #if CWDEBUG_DEBUGT || !LIBCWD_USE_LINUXTHREADS
00621 if (S_initialized)
00622 return;
00623 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Calling initialize() instance " << instance);
00624 mutex_tct<readers_instance>::initialize();
00625 S_no_holders_condition.initialize();
00626 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Leaving initialize() instance " << instance);
00627 S_initialized = true;
00628 #endif
00629 }
00630 static bool tryrdlock(void)
00631 {
00632 #if CWDEBUG_DEBUGT
00633 LIBCWD_TSD_DECLARATION;
00634 #endif
00635 LibcwDebugThreads( LIBCWD_ASSERT( S_initialized ) );
00636 LIBCWD_DEBUGDEBUG_ASSERT_CANCEL_DEFERRED;
00637 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Calling rwlock_tct<" << instance << ">::tryrdlock()");
00638 if (instance < end_recursive_types && pthread_equal(S_writer_id, pthread_self()))
00639 {
00640 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Leaving rwlock_tct<" << instance << ">::tryrdlock() (skipped: thread has write lock)");
00641 return true;
00642 }
00643
00644 if (S_writer_is_waiting || !S_no_holders_condition.trylock())
00645 return false;
00646 bool success = (S_holders_count != -1);
00647 if (success)
00648 ++S_holders_count;
00649 S_no_holders_condition.unlock();
00650 LibcwDebugThreads(
00651 if (success)
00652 {
00653 ++__libcwd_tsd.inside_critical_area;
00654 _private_::test_for_deadlock(instance, __libcwd_tsd, __builtin_return_address(0));
00655 __libcwd_tsd.instance_rdlocked[instance] += 1;
00656 if (__libcwd_tsd.instance_rdlocked[instance] == 1)
00657 {
00658 __libcwd_tsd.rdlocked_by1[instance] = pthread_self();
00659 __libcwd_tsd.rdlocked_from1[instance] = __builtin_return_address(0);
00660 }
00661 else if (__libcwd_tsd.instance_rdlocked[instance] == 2)
00662 {
00663 __libcwd_tsd.rdlocked_by2[instance] = pthread_self();
00664 __libcwd_tsd.rdlocked_from2[instance] = __builtin_return_address(0);
00665 }
00666 else
00667 core_dump();
00668 }
00669 );
00670 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Leaving rwlock_tct<" << instance << ">::tryrdlock()");
00671 return success;
00672 }
00673 static bool trywrlock(void)
00674 {
00675 LibcwDebugThreads( LIBCWD_ASSERT( S_initialized ) );
00676 #if CWDEBUG_DEBUGT
00677 LIBCWD_TSD_DECLARATION;
00678 #endif
00679 LIBCWD_DEBUGDEBUG_ASSERT_CANCEL_DEFERRED;
00680 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Calling rwlock_tct<" << instance << ">::trywrlock()");
00681 bool success;
00682 if ((success = mutex_tct<readers_instance>::trylock()))
00683 {
00684 S_writer_is_waiting = true;
00685 if ((success = S_no_holders_condition.trylock()))
00686 {
00687 if ((success = (S_holders_count == 0)))
00688 {
00689 S_holders_count = -1;
00690 if (instance < end_recursive_types)
00691 S_writer_id = pthread_self();
00692 #if CWDEBUG_DEBUG || CWDEBUG_DEBUGT
00693 #if CWDEBUG_DEBUGT
00694 _private_::test_for_deadlock(instance, __libcwd_tsd, __builtin_return_address(0));
00695 #endif
00696 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": rwlock_tct::trywrlock(): instance_locked[" << instance << "] == " << instance_locked[instance] << "; incrementing it.");
00697 instance_locked[instance] += 1;
00698 #if CWDEBUG_DEBUGT
00699 locked_by[instance] = pthread_self();
00700 locked_from[instance] = __builtin_return_address(0);
00701 #endif
00702 #endif
00703 }
00704 S_no_holders_condition.unlock();
00705 }
00706 S_writer_is_waiting = false;
00707 mutex_tct<readers_instance>::unlock();
00708 }
00709 LibcwDebugThreads( if (success) { ++__libcwd_tsd.inside_critical_area; } );
00710 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Leaving rwlock_tct<" << instance << ">::trywrlock()");
00711 return success;
00712 }
00713 static void rdlock(bool high_priority = false)
00714 {
00715 LibcwDebugThreads( LIBCWD_ASSERT( S_initialized ) );
00716 #if CWDEBUG_DEBUGT
00717 LIBCWD_TSD_DECLARATION;
00718 #endif
00719 LIBCWD_DEBUGDEBUG_ASSERT_CANCEL_DEFERRED;
00720 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Calling rwlock_tct<" << instance << ">::rdlock()");
00721 if (instance < end_recursive_types && pthread_equal(S_writer_id, pthread_self()))
00722 {
00723 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Leaving rwlock_tct<" << instance << ">::rdlock() (skipped: thread has write lock)");
00724 return;
00725 }
00726
00727 if (S_writer_is_waiting)
00728 {
00729 if (!high_priority)
00730 {
00731 mutex_tct<readers_instance>::lock();
00732 mutex_tct<readers_instance>::unlock();
00733 }
00734 }
00735 #if CWDEBUG_DEBUGT
00736 __libcwd_tsd.waiting_for_rdlock = instance;
00737 #endif
00738 S_no_holders_condition.lock();
00739 while (S_holders_count == -1)
00740 S_no_holders_condition.wait();
00741 #if CWDEBUG_DEBUGT
00742 __libcwd_tsd.waiting_for_rdlock = 0;
00743 #endif
00744 ++S_holders_count;
00745 S_no_holders_condition.unlock();
00746 LibcwDebugThreads(
00747 ++__libcwd_tsd.inside_critical_area;
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760 _private_::test_for_deadlock(instance + (high_priority ? high_priority_read_lock_offset : read_lock_offset), __libcwd_tsd, __builtin_return_address(0));
00761 __libcwd_tsd.instance_rdlocked[instance] += 1;
00762 if (__libcwd_tsd.instance_rdlocked[instance] == 1)
00763 {
00764 __libcwd_tsd.rdlocked_by1[instance] = pthread_self();
00765 __libcwd_tsd.rdlocked_from1[instance] = __builtin_return_address(0);
00766 }
00767 else if (__libcwd_tsd.instance_rdlocked[instance] == 2)
00768 {
00769 __libcwd_tsd.rdlocked_by2[instance] = pthread_self();
00770 __libcwd_tsd.rdlocked_from2[instance] = __builtin_return_address(0);
00771 }
00772 else
00773 core_dump();
00774 );
00775 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Leaving rwlock_tct<" << instance << ">::rdlock()");
00776 }
00777 static void rdunlock(void)
00778 {
00779 #if CWDEBUG_DEBUGT
00780 LIBCWD_TSD_DECLARATION;
00781 #endif
00782 LIBCWD_DEBUGDEBUG_ASSERT_CANCEL_DEFERRED;
00783 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Calling rwlock_tct<" << instance << ">::rdunlock()");
00784 if (instance < end_recursive_types && pthread_equal(S_writer_id, pthread_self()))
00785 {
00786 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Leaving rwlock_tct<" << instance << ">::rdunlock() (skipped: thread has write lock)");
00787 return;
00788 }
00789 LibcwDebugThreads( --__libcwd_tsd.inside_critical_area );
00790 S_no_holders_condition.lock();
00791 if (--S_holders_count == 0)
00792 S_no_holders_condition.signal();
00793 S_no_holders_condition.unlock();
00794 LibcwDebugThreads(
00795 if (__libcwd_tsd.instance_rdlocked[instance] == 2)
00796 __libcwd_tsd.rdlocked_by2[instance] = 0;
00797 else
00798 __libcwd_tsd.rdlocked_by1[instance] = 0;
00799 __libcwd_tsd.instance_rdlocked[instance] -= 1;
00800 );
00801 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Leaving rwlock_tct<" << instance << ">::rdunlock()");
00802 }
00803 static void wrlock(void)
00804 {
00805 LibcwDebugThreads( LIBCWD_ASSERT( S_initialized ) );
00806 #if CWDEBUG_DEBUGT
00807 LIBCWD_TSD_DECLARATION;
00808 #endif
00809 LIBCWD_DEBUGDEBUG_ASSERT_CANCEL_DEFERRED;
00810 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Calling rwlock_tct<" << instance << ">::wrlock()");
00811 mutex_tct<readers_instance>::lock();
00812 S_writer_is_waiting = true;
00813 #if CWDEBUG_DEBUGT
00814 __libcwd_tsd.waiting_for_lock = instance;
00815 #endif
00816 S_no_holders_condition.lock();
00817 while (S_holders_count != 0)
00818 S_no_holders_condition.wait();
00819 #if CWDEBUG_DEBUGT
00820 __libcwd_tsd.waiting_for_lock = 0;
00821 #endif
00822 S_writer_is_waiting = false;
00823 mutex_tct<readers_instance>::unlock();
00824 S_holders_count = -1;
00825 S_no_holders_condition.unlock();
00826 if (instance < end_recursive_types)
00827 S_writer_id = pthread_self();
00828 LibcwDebugThreads( ++__libcwd_tsd.inside_critical_area );
00829 #if CWDEBUG_DEBUG || CWDEBUG_DEBUGT
00830 #if CWDEBUG_DEBUGT
00831 _private_::test_for_deadlock(instance, __libcwd_tsd, __builtin_return_address(0));
00832 #endif
00833 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": rwlock_tct::wrlock(): instance_locked[" << instance << "] == " << instance_locked[instance] << "; incrementing it.");
00834 instance_locked[instance] += 1;
00835 #if CWDEBUG_DEBUGT
00836 locked_by[instance] = pthread_self();
00837 locked_from[instance] = __builtin_return_address(0);
00838 #endif
00839 #endif
00840 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Leaving rwlock_tct<" << instance << ">::wrlock()");
00841 }
00842 static void wrunlock(void)
00843 {
00844 #if CWDEBUG_DEBUGT
00845 LIBCWD_TSD_DECLARATION;
00846 #endif
00847 LIBCWD_DEBUGDEBUG_ASSERT_CANCEL_DEFERRED;
00848 #if CWDEBUG_DEBUG || CWDEBUG_DEBUGT
00849 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": rwlock_tct::wrunlock(): instance_locked[" << instance << "] == " << instance_locked[instance] << "; decrementing it.");
00850 #if CWDEBUG_DEBUGT
00851 LIBCWD_ASSERT( instance_locked[instance] > 0 && locked_by[instance] == pthread_self() );
00852 #endif
00853 instance_locked[instance] -= 1;
00854 #endif
00855 #if CWDEBUG_DEBUGT
00856 if (instance > end_recursive_types || instance_locked[instance] == 0)
00857 {
00858 locked_by[instance] = 0;
00859 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": rwlock_tct::unlock(): locked_by[" << instance << "] was reset.");
00860 }
00861 else
00862 {
00863 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": rwlock_tct::wrunlock(): locked_by[" << instance << "] was not reset, it still is " << locked_by[instance] << ".");
00864 }
00865 #endif
00866 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Calling rwlock_tct<" << instance << ">::wrunlock()");
00867 LibcwDebugThreads( --__libcwd_tsd.inside_critical_area) ;
00868 if (instance < end_recursive_types)
00869 S_writer_id = 0;
00870 S_no_holders_condition.lock();
00871 S_holders_count = 0;
00872 S_no_holders_condition.signal();
00873 S_no_holders_condition.unlock();
00874 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Leaving rwlock_tct<" << instance << ">::wrunlock()");
00875 }
00876 static void rd2wrlock(void)
00877 {
00878 #if CWDEBUG_DEBUGT
00879 LIBCWD_TSD_DECLARATION;
00880 #endif
00881 LIBCWD_DEBUGDEBUG_ASSERT_CANCEL_DEFERRED;
00882 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Calling rwlock_tct<" << instance << ">::rd2wrlock()");
00883 #if CWDEBUG_DEBUGT
00884 __libcwd_tsd.waiting_for_lock = instance;
00885 #endif
00886 S_no_holders_condition.lock();
00887 if (--S_holders_count > 0)
00888 {
00889 mutex_tct<readers_instance>::lock();
00890 S_writer_is_waiting = true;
00891 while (S_holders_count != 0)
00892 S_no_holders_condition.wait();
00893 S_writer_is_waiting = false;
00894 mutex_tct<readers_instance>::unlock();
00895 }
00896 #if CWDEBUG_DEBUGT
00897 __libcwd_tsd.waiting_for_lock = 0;
00898 #endif
00899 S_holders_count = -1;
00900 S_no_holders_condition.unlock();
00901 if (instance < end_recursive_types)
00902 S_writer_id = pthread_self();
00903 #if CWDEBUG_DEBUG || CWDEBUG_DEBUGT
00904 #if CWDEBUG_DEBUGT
00905 _private_::test_for_deadlock(instance, __libcwd_tsd, __builtin_return_address(0));
00906 #endif
00907 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": rwlock_tct::rd2wrlock(): instance_locked[" << instance << "] == " << instance_locked[instance] << "; incrementing it.");
00908 instance_locked[instance] += 1;
00909 #if CWDEBUG_DEBUGT
00910 locked_by[instance] = pthread_self();
00911 locked_from[instance] = __builtin_return_address(0);
00912 #endif
00913 #endif
00914 LibcwDebugThreads(
00915 if (__libcwd_tsd.instance_rdlocked[instance] == 2)
00916 __libcwd_tsd.rdlocked_by2[instance] = 0;
00917 else
00918 __libcwd_tsd.rdlocked_by1[instance] = 0;
00919 __libcwd_tsd.instance_rdlocked[instance] -= 1;
00920 );
00921 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Leaving rwlock_tct<" << instance << ">::rd2wrlock()");
00922 }
00923 static void wr2rdlock(void)
00924 {
00925 #if CWDEBUG_DEBUGT
00926 LIBCWD_TSD_DECLARATION;
00927 #endif
00928 LIBCWD_DEBUGDEBUG_ASSERT_CANCEL_DEFERRED;
00929 #if CWDEBUG_DEBUG || CWDEBUG_DEBUGT
00930 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": rwlock_tct::wr2rdlock(): instance_locked[" << instance << "] == " << instance_locked[instance] << "; decrementing it.");
00931 #if CWDEBUG_DEBUGT
00932 LIBCWD_ASSERT( instance_locked[instance] > 0 && locked_by[instance] == pthread_self() );
00933 #endif
00934 instance_locked[instance] -= 1;
00935 #if CWDEBUG_DEBUGT
00936 if (instance > end_recursive_types || instance_locked[instance] == 0)
00937 {
00938 locked_by[instance] = 0;
00939 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": rwlock_tct::wr2rdlock(): locked_by[" << instance << "] was reset.");
00940 }
00941 else
00942 {
00943 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": rwlock_tct::wr2rdlock(): locked_by[" << instance << "] was not reset, it still is " << locked_by[instance] << ".");
00944 }
00945 #endif
00946 #endif
00947 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Calling rwlock_tct<" << instance << ">::wr2rdlock()");
00948 if (instance < end_recursive_types)
00949 S_writer_id = 0;
00950 S_holders_count = 1;
00951 LibcwDebugThreads(
00952 _private_::test_for_deadlock(instance, __libcwd_tsd, __builtin_return_address(0));
00953 if (instance >= instance_rdlocked_size)
00954 core_dump();
00955 __libcwd_tsd.instance_rdlocked[instance] += 1;
00956 if (__libcwd_tsd.instance_rdlocked[instance] == 1)
00957 {
00958 __libcwd_tsd.rdlocked_by1[instance] = pthread_self();
00959 __libcwd_tsd.rdlocked_from1[instance] = __builtin_return_address(0);
00960 }
00961 else if (__libcwd_tsd.instance_rdlocked[instance] == 2)
00962 {
00963 __libcwd_tsd.rdlocked_by2[instance] = pthread_self();
00964 __libcwd_tsd.rdlocked_from2[instance] = __builtin_return_address(0);
00965 }
00966 else
00967 core_dump();
00968 );
00969 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Leaving rwlock_tct<" << instance << ">::wr2rdlock()");
00970 }
00971
00972 static void cleanup(void*);
00973 };
00974
00975 template <int instance>
00976 int rwlock_tct<instance>::S_holders_count = 0;
00977
00978 template <int instance>
00979 bool volatile rwlock_tct<instance>::S_writer_is_waiting = 0;
00980
00981 template <int instance>
00982 pthread_t rwlock_tct<instance>::S_writer_id = 0;
00983
00984 #if CWDEBUG_DEBUGT || !LIBCWD_USE_LINUXTHREADS
00985 template <int instance>
00986 bool rwlock_tct<instance>::S_initialized = 0;
00987 #endif
00988
00989 template <int instance>
00990 typename rwlock_tct<instance>::cond_t rwlock_tct<instance>::S_no_holders_condition;
00991
00992 template <int instance>
00993 void rwlock_tct<instance>::cleanup(void*)
00994 {
00995 if (S_holders_count == -1)
00996 wrunlock();
00997 else
00998 rdunlock();
00999 }
01000
01001 extern void fatal_cancellation(void*);
01002
01003 }
01004 }
01005
01006 #else // !LIBCWD_THREAD_SAFE
01007 #define LIBCWD_DISABLE_CANCEL
01008 #define LIBCWD_DISABLE_CANCEL_NO_BRACE
01009 #define LIBCWD_ENABLE_CANCEL_NO_BRACE
01010 #define LIBCWD_ENABLE_CANCEL
01011 #define LIBCWD_DEFER_CANCEL
01012 #define LIBCWD_DEFER_CANCEL_NO_BRACE
01013 #define LIBCWD_RESTORE_CANCEL_NO_BRACE
01014 #define LIBCWD_RESTORE_CANCEL
01015 #define LIBCWD_DEFER_CLEANUP_PUSH(routine, arg)
01016 #define LIBCWD_CLEANUP_POP_RESTORE(execute)
01017 #define LIBCWD_PUSH_DEFER_TRYLOCK_MUTEX(instance, unlock_routine)
01018 #define LIBCWD_DEFER_PUSH_LOCKMUTEX(instance, unlock_routine)
01019 #define LIBCWD_UNLOCKMUTEX_POP_RESTORE(instance)
01020 #define LIBCWD_DEBUGDEBUG_ASSERT_CANCEL_DEFERRED
01021 #endif // LIBCWD_THREAD_SAFE
01022 #endif // LIBCWD_PRIVATE_THREADING_H
01023