00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifndef _STLP_INTERNAL_THREADS_H
00026 #define _STLP_INTERNAL_THREADS_H
00027
00028
00029
00030
00031
00032
00033 #ifndef _STLP_CONFIG_H
00034 #include <stl/_config.h>
00035 #endif
00036
00037 # if ! defined (_STLP_CSTDDEF)
00038 # include <cstddef>
00039 # endif
00040
00041 # if ! defined (_STLP_CSTDLIB)
00042 # include <cstdlib>
00043 # endif
00044
00045
00046 # if defined (__sun) || ( defined(__GNUC__) && defined(__APPLE__) && !defined (__SYMBIAN32__))
00047 # define _STLP_MUTEX_INITIALIZER
00048 # endif
00049
00050 # if defined (_STLP_WIN32) || defined (__sgi) || defined (_STLP_SPARC_SOLARIS_THREADS)
00051 typedef long __stl_atomic_t;
00052 # else
00053 # if defined (_STLP_USE_NAMESPACES) && ! defined (_STLP_VENDOR_GLOBAL_CSTD)
00054 using _STLP_VENDOR_CSTD::size_t;
00055 # endif
00056 typedef size_t __stl_atomic_t;
00057 #endif
00058
00059 # if defined(_STLP_SGI_THREADS)
00060 # include <mutex.h>
00061
00062 #if !defined(__add_and_fetch) && \
00063 (__mips < 3 || !(defined (_ABIN32) || defined(_ABI64)))
00064 # define __add_and_fetch(__l,__v) add_then_test((unsigned long*)__l,__v)
00065 # define __test_and_set(__l,__v) test_and_set(__l,__v)
00066 #endif
00067
00068 # if __mips < 3 || !(defined (_ABIN32) || defined(_ABI64))
00069 # define _STLP_ATOMIC_EXCHANGE(__p, __q) test_and_set(__p, __q)
00070 # else
00071 # define _STLP_ATOMIC_EXCHANGE(__p, __q) __test_and_set((unsigned long*)__p, (unsigned long)__q)
00072 # endif
00073
00074 # define _STLP_ATOMIC_INCREMENT(__x) __add_and_fetch(__x, 1)
00075 # define _STLP_ATOMIC_DECREMENT(__x) __add_and_fetch(__x, (size_t) -1)
00076 # elif defined(_STLP_PTHREADS)
00077 # include <pthread.h>
00078 # if defined (PTHREAD_MUTEX_INITIALIZER) && ! defined (_STLP_MUTEX_INITIALIZER) && defined (_REENTRANT)
00079 # define _STLP_MUTEX_INITIALIZER = { PTHREAD_MUTEX_INITIALIZER }
00080 # endif
00081
00082
00083 # if defined(_DECTHREADS_) && ( defined (_PTHREAD_USE_D4) || defined (__hpux)) \
00084 && ! defined (_CMA_SUPPRESS_EXTERNALS_)
00085 # define _STLP_PTHREAD_ATTR_DEFAULT pthread_mutexattr_default
00086 # else
00087 # define _STLP_PTHREAD_ATTR_DEFAULT 0
00088 # endif
00089
00090 # elif defined(_STLP_WIN32)
00091 # if !defined (_STLP_WINDOWS_H_INCLUDED) && ! defined (_WINDOWS_) && ! defined (__WINDOWS__) && ! defined (_WINDOWS_H)
00092 # if ! (defined ( _STLP_MSVC ) || defined (__BORLANDC__) || defined (__ICL) || defined (__WATCOMC__) || defined (__MINGW32__))
00093 # ifdef _STLP_USE_MFC
00094 # include <afx.h>
00095 # else
00096 # include <windows.h>
00097 # endif
00098 # else
00099
00100 extern "C" {
00101 # if (defined(_M_MRX000) || defined(_M_ALPHA) \
00102 || (defined(_M_PPC) && (_MSC_VER >= 1000))) && !defined(RC_INVOKED) && !defined (__SYMBIAN32__)
00103 # define InterlockedIncrement _InterlockedIncrement
00104 # define InterlockedDecrement _InterlockedDecrement
00105 # define InterlockedExchange _InterlockedExchange
00106 # define _STLP_STDCALL
00107 # else
00108 # ifdef _MAC
00109 # define _STLP_STDCALL _cdecl
00110 # else
00111 # define _STLP_STDCALL __stdcall
00112 # endif
00113 # endif
00114
00115 #if (_MSC_VER >= 1300) || defined (_STLP_NEW_PLATFORM_SDK) && !defined (__SYMBIAN32__)
00116 _STLP_IMPORT_DECLSPEC long _STLP_STDCALL InterlockedIncrement(long volatile *);
00117 _STLP_IMPORT_DECLSPEC long _STLP_STDCALL InterlockedDecrement(long volatile *);
00118 _STLP_IMPORT_DECLSPEC long _STLP_STDCALL InterlockedExchange(long volatile *, long);
00119 #else
00120
00121
00122 _STLP_IMPORT_DECLSPEC long _STLP_STDCALL InterlockedIncrement(long*);
00123 _STLP_IMPORT_DECLSPEC long _STLP_STDCALL InterlockedDecrement(long*);
00124 _STLP_IMPORT_DECLSPEC long _STLP_STDCALL InterlockedExchange(long*, long);
00125 #endif
00126
00127 _STLP_IMPORT_DECLSPEC void _STLP_STDCALL Sleep(unsigned long);
00128 _STLP_IMPORT_DECLSPEC void _STLP_STDCALL OutputDebugStringA( const char* lpOutputString );
00129
00130 # if defined (InterlockedIncrement)
00131 # pragma intrinsic(_InterlockedIncrement)
00132 # pragma intrinsic(_InterlockedDecrement)
00133 # pragma intrinsic(_InterlockedExchange)
00134 # endif
00135 }
00136
00137 # endif
00138
00139 # define _STLP_WINDOWS_H_INCLUDED
00140
00141 # endif
00142
00143 # ifndef _STLP_ATOMIC_INCREMENT
00144 # define _STLP_ATOMIC_INCREMENT(__x) InterlockedIncrement((long*)__x)
00145 # define _STLP_ATOMIC_DECREMENT(__x) InterlockedDecrement((long*)__x)
00146 # define _STLP_ATOMIC_EXCHANGE(__x, __y) InterlockedExchange((long*)__x, (long)__y)
00147 # endif
00148 # elif defined(__DECC) || defined(__DECCXX)
00149 # include <machine/builtins.h>
00150 # define _STLP_ATOMIC_EXCHANGE __ATOMIC_EXCH_LONG
00151 # define _STLP_ATOMIC_INCREMENT(__x, __y) __ATOMIC_ADD_LONG(__x, 1)
00152 # define _STLP_ATOMIC_DECREMENT(__x, __y) __ATOMIC_ADD_LONG(__x, -1)
00153 # elif defined(_STLP_SPARC_SOLARIS_THREADS)
00154 # include <stl/_sparc_atomic.h>
00155 # elif defined (_STLP_UITHREADS)
00156
00157
00158
00159 # include <ctime>
00160 # if defined (_STLP_USE_NAMESPACES) && ! defined (_STLP_VENDOR_GLOBAL_CSTD)
00161 using _STLP_VENDOR_CSTD::time_t;
00162 # endif
00163 # include <synch.h>
00164 # include <cstdio>
00165 # include <cwchar>
00166 # elif defined (_STLP_BETHREADS)
00167 # include <OS.h>
00168 #include <cassert>
00169 #include <stdio.h>
00170 # define _STLP_MUTEX_INITIALIZER = { 0 }
00171 #elif defined(_STLP_OS2THREADS)
00172
00173 typedef unsigned long ULONG;
00174 #ifndef __HEV__
00175 #define __HEV__
00176 typedef ULONG HEV;
00177 typedef HEV* PHEV;
00178 #endif
00179 typedef ULONG APIRET;
00180 typedef ULONG HMTX;
00181 typedef HMTX* PHMTX;
00182 typedef const char* PCSZ;
00183 typedef ULONG BOOL32;
00184 APIRET _System DosCreateMutexSem(PCSZ pszName, PHEV phev, ULONG
00185 flAttr, BOOL32 fState);
00186 APIRET _System DosRequestMutexSem(HMTX hmtx, ULONG ulTimeout);
00187 APIRET _System DosReleaseMutexSem(HMTX hmtx);
00188 APIRET _System DosCloseMutexSem(HMTX hmtx);
00189 # define _STLP_MUTEX_INITIALIZER = { 0 };
00190
00191 # endif
00192
00193 # ifndef _STLP_MUTEX_INITIALIZER
00194 # if defined(_STLP_ATOMIC_EXCHANGE)
00195 # define _STLP_MUTEX_INITIALIZER = { 0 }
00196 # elif defined(_STLP_UITHREADS)
00197 # define _STLP_MUTEX_INITIALIZER = { DEFAULTMUTEX }
00198 # else
00199 # define _STLP_MUTEX_INITIALIZER
00200 # endif
00201 # endif
00202
00203 _STLP_BEGIN_NAMESPACE
00204
00205
00206 template <int __inst>
00207 struct _STLP_mutex_spin {
00208 enum { __low_max = 30, __high_max = 1000 };
00209
00210 static unsigned __max;
00211 static unsigned __last;
00212 static void _STLP_CALL _M_do_lock(volatile __stl_atomic_t* __lock);
00213 static void _STLP_CALL _S_nsec_sleep(int __log_nsec);
00214 };
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231 struct _STLP_CLASS_DECLSPEC _STLP_mutex_base
00232 {
00233 #if defined(_STLP_ATOMIC_EXCHANGE) || defined(_STLP_SGI_THREADS)
00234
00235 volatile __stl_atomic_t _M_lock;
00236 #endif
00237
00238 #ifdef _STLP_THREADS
00239
00240 #if defined (_STLP_ATOMIC_EXCHANGE)
00241 inline void _M_initialize() { _M_lock=0; }
00242 inline void _M_destroy() {}
00243
00244 void _M_acquire_lock() {
00245 _STLP_mutex_spin<0>::_M_do_lock(&_M_lock);
00246 }
00247
00248 inline void _M_release_lock() {
00249 volatile __stl_atomic_t* __lock = &_M_lock;
00250 # if defined(_STLP_SGI_THREADS) && (defined(__GNUC__) && !defined (__SYMBIAN32__)) && __mips >= 3
00251 asm("sync");
00252 *__lock = 0;
00253 # elif defined(_STLP_SGI_THREADS) && __mips >= 3 \
00254 && (defined (_ABIN32) || defined(_ABI64))
00255 __lock_release(__lock);
00256 # elif defined (_STLP_SPARC_SOLARIS_THREADS)
00257 # if defined (__WORD64) || defined (__arch64__) \
00258 || defined (__sparcv9) || defined (__sparcv8plus)
00259 asm("membar #StoreStore ; membar #LoadStore");
00260 # else
00261 asm(" stbar ");
00262 # endif
00263 *__lock = 0;
00264 # else
00265 *__lock = 0;
00266
00267
00268 # endif
00269 }
00270 #elif defined(_STLP_PTHREADS)
00271 pthread_mutex_t _M_lock;
00272 inline void _M_initialize() {
00273 pthread_mutex_init(&_M_lock,_STLP_PTHREAD_ATTR_DEFAULT);
00274 }
00275 inline void _M_destroy() {
00276 pthread_mutex_destroy(&_M_lock);
00277 }
00278 inline void _M_acquire_lock() {
00279
00280 #if defined ( __hpux ) && ! defined (PTHREAD_MUTEX_INITIALIZER)
00281 if (!_M_lock.field1) _M_initialize();
00282 #endif
00283 pthread_mutex_lock(&_M_lock);
00284 }
00285 inline void _M_release_lock() { pthread_mutex_unlock(&_M_lock); }
00286
00287 #elif defined (_STLP_UITHREADS)
00288 mutex_t _M_lock;
00289 inline void _M_initialize() {
00290 mutex_init(&_M_lock,0,NULL);
00291 }
00292 inline void _M_destroy() {
00293 mutex_destroy(&_M_lock);
00294 }
00295 inline void _M_acquire_lock() { mutex_lock(&_M_lock); }
00296 inline void _M_release_lock() { mutex_unlock(&_M_lock); }
00297
00298 #elif defined(_STLP_OS2THREADS)
00299 HMTX _M_lock;
00300 inline void _M_initialize() { DosCreateMutexSem(NULL, &_M_lock, 0,
00301 false); }
00302 inline void _M_destroy() { DosCloseMutexSem(_M_lock); }
00303 inline void _M_acquire_lock() {
00304 if(!_M_lock) _M_initialize();
00305 DosRequestMutexSem(_M_lock, -1);
00306 }
00307 inline void _M_release_lock() { DosReleaseMutexSem(_M_lock); }
00308 #elif defined(_STLP_BETHREADS)
00309 sem_id sem;
00310 inline void _M_initialize()
00311 {
00312 sem = create_sem(1, "STLPort");
00313 assert(sem > 0);
00314 }
00315 inline void _M_destroy()
00316 {
00317 int t = delete_sem(sem);
00318 assert(t == B_NO_ERROR);
00319 }
00320 inline void _M_acquire_lock();
00321 inline void _M_release_lock()
00322 {
00323 status_t t = release_sem(sem);
00324 assert(t == B_NO_ERROR);
00325 }
00326 #endif
00327 #else
00328 inline void _M_initialize() {}
00329 inline void _M_destroy() {}
00330 inline void _M_acquire_lock() {}
00331 inline void _M_release_lock() {}
00332 #endif
00333 };
00334
00335
00336
00337 #if defined(_STLP_ATOMIC_EXCHANGE) || defined(_STLP_BETHREADS)
00338 struct _STLP_CLASS_DECLSPEC _STLP_mutex_indirect : _STLP_mutex_base {};
00339 #else
00340 struct _STLP_CLASS_DECLSPEC _STLP_mutex_indirect
00341 {
00342 void* _M_lock;
00343
00344 # if defined(_STLP_PTHREADS)
00345 inline void _M_initialize() {
00346 _M_lock = (void*)_STLP_VENDOR_CSTD::calloc(1,sizeof(pthread_mutex_t));
00347 pthread_mutex_init((pthread_mutex_t*)_M_lock,_STLP_PTHREAD_ATTR_DEFAULT);
00348 }
00349 inline void _M_destroy() {
00350 pthread_mutex_destroy((pthread_mutex_t*)_M_lock);
00351 free((char*)_M_lock);
00352 }
00353 inline void _M_acquire_lock() {
00354 pthread_mutex_lock((pthread_mutex_t*)_M_lock);
00355 }
00356 inline void _M_release_lock() { pthread_mutex_unlock((pthread_mutex_t*)_M_lock); }
00357
00358 # elif defined (_STLP_UITHREADS)
00359 inline void _M_initialize() {
00360 _M_lock = (void*)calloc(1,sizeof(mutex_t));
00361 mutex_init((mutex_t*)_M_lock,0,NULL);
00362 }
00363 inline void _M_destroy() {
00364 mutex_destroy((mutex_t*)_M_lock);
00365 free((char*)_M_lock);
00366 }
00367 inline void _M_acquire_lock() { mutex_lock((mutex_t*)_M_lock); }
00368 inline void _M_release_lock() { mutex_unlock((mutex_t*)_M_lock); }
00369
00370 #elif defined(_STLP_OS2THREADS)
00371 inline void _M_initialize() {
00372 _M_lock = (void*)calloc(1,sizeof(HMTX));
00373 DosCreateMutexSem(NULL, (HMTX*)_M_lock, 0, false);
00374 }
00375 inline void _M_destroy() {
00376 DosCloseMutexSem(*(HMTX*)_M_lock);
00377 free((char*)_M_lock);
00378 }
00379 inline void _M_acquire_lock() {
00380 if(!_M_lock) _M_initialize();
00381 DosRequestMutexSem(*(HMTX*)_M_lock, -1);
00382 }
00383 inline void _M_release_lock() { DosReleaseMutexSem(*(HMTX*)_M_lock); }
00384 # else
00385 inline void _M_initialize() {}
00386 inline void _M_destroy() {}
00387 inline void _M_acquire_lock() {}
00388 inline void _M_release_lock() {}
00389 # endif
00390 };
00391 #endif
00392
00393
00394
00395
00396 struct _STLP_CLASS_DECLSPEC _STLP_mutex : public _STLP_mutex_indirect {
00397 inline _STLP_mutex () {
00398 _M_initialize();
00399 }
00400 inline ~_STLP_mutex () {
00401 _M_destroy();
00402 }
00403 private:
00404 _STLP_mutex(const _STLP_mutex&);
00405 void operator=(const _STLP_mutex&);
00406 };
00407
00408
00409
00410
00411
00412 struct _STLP_CLASS_DECLSPEC _Refcount_Base
00413 {
00414
00415 volatile __stl_atomic_t _M_ref_count;
00416
00417 # if !defined (_STLP_ATOMIC_EXCHANGE)
00418 _STLP_mutex _M_mutex;
00419 # endif
00420
00421
00422 _Refcount_Base(__stl_atomic_t __n) : _M_ref_count(__n) {}
00423
00424
00425 # if defined (_STLP_THREADS) && defined ( _STLP_ATOMIC_EXCHANGE )
00426 void _M_incr() { _STLP_ATOMIC_INCREMENT((__stl_atomic_t*)&_M_ref_count); }
00427 void _M_decr() { _STLP_ATOMIC_DECREMENT((__stl_atomic_t*)&_M_ref_count); }
00428 # elif defined(_STLP_THREADS)
00429 void _M_incr() {
00430 _M_mutex._M_acquire_lock();
00431 ++_M_ref_count;
00432 _M_mutex._M_release_lock();
00433 }
00434 void _M_decr() {
00435 _M_mutex._M_acquire_lock();
00436 --_M_ref_count;
00437 _M_mutex._M_release_lock();
00438 }
00439 # else
00440 void _M_incr() { ++_M_ref_count; }
00441 void _M_decr() { --_M_ref_count; }
00442 # endif
00443 };
00444
00445
00446
00447
00448
00449 # if defined (_STLP_THREADS) && defined ( _STLP_ATOMIC_EXCHANGE )
00450 inline __stl_atomic_t _Atomic_swap(volatile __stl_atomic_t * __p, __stl_atomic_t __q) {
00451 return (__stl_atomic_t) _STLP_ATOMIC_EXCHANGE(__p,__q);
00452 }
00453 # elif defined(_STLP_PTHREADS) || defined (_STLP_UITHREADS) || defined (_STLP_OS2THREADS)
00454
00455 template<int __dummy>
00456 struct _Swap_lock_struct {
00457 static _STLP_STATIC_MUTEX _S_swap_lock;
00458 };
00459
00460
00461
00462
00463
00464 inline __stl_atomic_t _Atomic_swap(volatile __stl_atomic_t * __p, __stl_atomic_t __q) {
00465 _Swap_lock_struct<0>::_S_swap_lock._M_acquire_lock();
00466 __stl_atomic_t __result = *__p;
00467 *__p = __q;
00468 _Swap_lock_struct<0>::_S_swap_lock._M_release_lock();
00469 return __result;
00470 }
00471 # else
00472
00473 static inline __stl_atomic_t _STLP_CALL
00474 _Atomic_swap(volatile __stl_atomic_t * __p, __stl_atomic_t __q) {
00475 __stl_atomic_t __result = *__p;
00476 *__p = __q;
00477 return __result;
00478 }
00479 # endif
00480
00481
00482
00483
00484
00485
00486
00487 struct _STLP_CLASS_DECLSPEC _STLP_auto_lock
00488 {
00489 _STLP_STATIC_MUTEX& _M_lock;
00490
00491 _STLP_auto_lock(_STLP_STATIC_MUTEX& __lock) : _M_lock(__lock)
00492 { _M_lock._M_acquire_lock(); }
00493 ~_STLP_auto_lock() { _M_lock._M_release_lock(); }
00494
00495 private:
00496 void operator=(const _STLP_auto_lock&);
00497 _STLP_auto_lock(const _STLP_auto_lock&);
00498 };
00499
00500
00501
00502 #ifdef _STLP_BETHREADS
00503
00504 template <int __inst>
00505 struct _STLP_beos_static_lock_data
00506 {
00507 static bool is_init;
00508 struct mutex_t : public _STLP_mutex
00509 {
00510 mutex_t()
00511 {
00512 _STLP_beos_static_lock_data<0>::is_init = true;
00513 }
00514 ~mutex_t()
00515 {
00516 _STLP_beos_static_lock_data<0>::is_init = false;
00517 }
00518 };
00519 static mutex_t mut;
00520 };
00521
00522 template <int __inst>
00523 bool _STLP_beos_static_lock_data<__inst>::is_init = false;
00524 template <int __inst>
00525 typename _STLP_beos_static_lock_data<__inst>::mutex_t _STLP_beos_static_lock_data<__inst>::mut;
00526
00527
00528 inline void _STLP_mutex_base::_M_acquire_lock()
00529 {
00530 if(sem == 0)
00531 {
00532
00533
00534
00535 if(_STLP_beos_static_lock_data<0>::is_init)
00536 {
00537 _STLP_auto_lock al(_STLP_beos_static_lock_data<0>::mut);
00538 if(sem == 0) _M_initialize();
00539 }
00540 else
00541 {
00542
00543
00544
00545 _M_initialize();
00546 }
00547 }
00548 status_t t;
00549 t = acquire_sem(sem);
00550 assert(t == B_NO_ERROR);
00551 }
00552
00553 #endif
00554
00555 _STLP_END_NAMESPACE
00556
00557 # if !defined (_STLP_LINK_TIME_INSTANTIATION)
00558 # include <stl/_threads.c>
00559 # endif
00560
00561 #endif
00562
00563
00564
00565