Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygen_threads.h
Go to the documentation of this file.
00001 /* 00002 * Copyright (c) 1997-1999 00003 * Silicon Graphics Computer Systems, Inc. 00004 * 00005 * Copyright (c) 1999 00006 * Boris Fomitchev 00007 * 00008 * This material is provided "as is", with absolutely no warranty expressed 00009 * or implied. Any use is at your own risk. 00010 * 00011 * Permission to use or copy this software for any purpose is hereby granted 00012 * without fee, provided the above notices are retained on all copies. 00013 * Permission to modify the code and to distribute modified code is granted, 00014 * provided the above notices are retained, and a notice that the code was 00015 * modified is included with the above copyright notice. 00016 * 00017 */ 00018 00019 // WARNING: This is an internal header file, included by other C++ 00020 // standard library headers. You should not attempt to use this header 00021 // file directly. 00022 00023 00024 #ifndef _STLP_INTERNAL_THREADS_H 00025 #define _STLP_INTERNAL_THREADS_H 00026 00027 // Supported threading models are native SGI, pthreads, uithreads 00028 // (similar to pthreads, but based on an earlier draft of the Posix 00029 // threads standard), and Win32 threads. Uithread support by Jochen 00030 // Schlick, 1999, and Solaris threads generalized to them. 00031 00032 #ifndef _STLP_INTERNAL_CSTDDEF 00033 # include <stl/_cstddef.h> 00034 #endif 00035 00036 #ifndef _STLP_INTERNAL_CSTDLIB 00037 # include <stl/_cstdlib.h> 00038 #endif 00039 00040 // On SUN and Mac OS X gcc, zero-initialization works just fine... 00041 #if defined (__sun) || (defined (__GNUC__) && defined(__APPLE__)) 00042 # define _STLP_MUTEX_INITIALIZER 00043 #endif 00044 00045 /* This header defines the following atomic operation that platform should 00046 * try to support as much as possible. Atomic operation are exposed as macro 00047 * in order to easily test for their existance. They are: 00048 * __stl_atomic_t _STLP_ATOMIC_INCREMENT(volatile __stl_atomic_t* __ptr) : 00049 * increment *__ptr by 1 and returns the new value 00050 * __stl_atomic_t _STLP_ATOMIC_DECREMENT(volatile __stl_atomic_t* __ptr) : 00051 * decrement *__ptr by 1 and returns the new value 00052 * __stl_atomic_t _STLP_ATOMIC_EXCHANGE(volatile __stl_atomic_t* __target, __stl_atomic_t __val) : 00053 * assign __val to *__target and returns former *__target value 00054 * void* _STLP_ATOMIC_EXCHANGE_PTR(void* volatile* __target, void* __ptr) : 00055 * assign __ptr to *__target and returns former *__target value 00056 */ 00057 00058 #if defined (_STLP_THREADS) 00059 00060 # if defined (_STLP_SGI_THREADS) 00061 00062 # include <mutex.h> 00063 // Hack for SGI o32 compilers. 00064 # if !defined(__add_and_fetch) && \ 00065 (__mips < 3 || !(defined (_ABIN32) || defined(_ABI64))) 00066 # define __add_and_fetch(__l,__v) add_then_test((unsigned long*)__l,__v) 00067 # define __test_and_set(__l,__v) test_and_set(__l,__v) 00068 # endif /* o32 */ 00069 00070 # if __mips < 3 || !(defined (_ABIN32) || defined(_ABI64)) 00071 # define _STLP_ATOMIC_EXCHANGE(__p, __q) test_and_set(__p, __q) 00072 # else 00073 # define _STLP_ATOMIC_EXCHANGE(__p, __q) __test_and_set((unsigned long*)__p, (unsigned long)__q) 00074 # endif 00075 00076 # define _STLP_ATOMIC_INCREMENT(__x) __add_and_fetch(__x, 1) 00077 # define _STLP_ATOMIC_DECREMENT(__x) __add_and_fetch(__x, (size_t) -1) 00078 typedef long __stl_atomic_t; 00079 00080 # elif defined (_STLP_PTHREADS) 00081 00082 # include <pthread.h> 00083 # if !defined (_STLP_USE_PTHREAD_SPINLOCK) 00084 # if defined (PTHREAD_MUTEX_INITIALIZER) && !defined (_STLP_MUTEX_INITIALIZER) && defined (_REENTRANT) 00085 # define _STLP_MUTEX_INITIALIZER = { PTHREAD_MUTEX_INITIALIZER } 00086 # endif 00087 //HPUX variants have (on some platforms optional) non-standard "DCE" pthreads impl 00088 # if defined (_DECTHREADS_) && (defined (_PTHREAD_USE_D4) || defined (__hpux)) && !defined (_CMA_SUPPRESS_EXTERNALS_) 00089 # define _STLP_PTHREAD_ATTR_DEFAULT pthread_mutexattr_default 00090 # else 00091 # define _STLP_PTHREAD_ATTR_DEFAULT 0 00092 # endif 00093 # else 00094 # if defined (__OpenBSD__) 00095 # include <spinlock.h> 00096 # endif 00097 # endif 00098 00099 # if defined (__GNUC__) && defined (__i386__) 00100 # if !defined (_STLP_ATOMIC_INCREMENT) 00101 inline long _STLP_atomic_increment_gcc_x86(long volatile* p) { 00102 long result; 00103 __asm__ __volatile__ 00104 ("lock; xaddl %1, %0;" 00105 :"=m" (*p), "=r" (result) 00106 :"m" (*p), "1" (1) 00107 :"cc"); 00108 return result + 1; 00109 } 00110 # define _STLP_ATOMIC_INCREMENT(__x) (_STLP_atomic_increment_gcc_x86((long volatile*)__x)) 00111 # endif 00112 00113 # if !defined (_STLP_ATOMIC_DECREMENT) 00114 inline long _STLP_atomic_decrement_gcc_x86(long volatile* p) { 00115 long result; 00116 __asm__ __volatile__ 00117 ("lock; xaddl %1, %0;" 00118 :"=m" (*p), "=r" (result) 00119 :"m" (*p), "1" (-1) 00120 :"cc"); 00121 return result - 1; 00122 } 00123 # define _STLP_ATOMIC_DECREMENT(__x) (_STLP_atomic_decrement_gcc_x86((long volatile*)__x)) 00124 # endif 00125 typedef long __stl_atomic_t; 00126 # else 00127 typedef size_t __stl_atomic_t; 00128 # endif /* if defined(__GNUC__) && defined(__i386__) */ 00129 00130 # elif defined (_STLP_WIN32THREADS) 00131 00132 # if !defined (_STLP_ATOMIC_INCREMENT) 00133 # if !defined (_STLP_NEW_PLATFORM_SDK) 00134 # define _STLP_ATOMIC_INCREMENT(__x) InterlockedIncrement(__CONST_CAST(long*, __x)) 00135 # define _STLP_ATOMIC_DECREMENT(__x) InterlockedDecrement(__CONST_CAST(long*, __x)) 00136 # define _STLP_ATOMIC_EXCHANGE(__x, __y) InterlockedExchange(__CONST_CAST(long*, __x), __y) 00137 # else 00138 # define _STLP_ATOMIC_INCREMENT(__x) InterlockedIncrement(__x) 00139 # define _STLP_ATOMIC_DECREMENT(__x) InterlockedDecrement(__x) 00140 # define _STLP_ATOMIC_EXCHANGE(__x, __y) InterlockedExchange(__x, __y) 00141 # endif 00142 # define _STLP_ATOMIC_EXCHANGE_PTR(__x, __y) STLPInterlockedExchangePointer(__x, __y) 00143 # endif 00144 typedef long __stl_atomic_t; 00145 00146 # elif defined (__DECC) || defined (__DECCXX) 00147 00148 # include <machine/builtins.h> 00149 # define _STLP_ATOMIC_EXCHANGE __ATOMIC_EXCH_LONG 00150 # define _STLP_ATOMIC_INCREMENT(__x) __ATOMIC_ADD_LONG(__x, 1) 00151 # define _STLP_ATOMIC_DECREMENT(__x) __ATOMIC_ADD_LONG(__x, -1) 00152 typedef long __stl_atomic_t; 00153 00154 # elif defined (_STLP_SPARC_SOLARIS_THREADS) 00155 00156 typedef long __stl_atomic_t; 00157 # include <stl/_sparc_atomic.h> 00158 00159 # elif defined (_STLP_UITHREADS) 00160 00161 // this inclusion is potential hazard to bring up all sorts 00162 // of old-style headers. Let's assume vendor already know how 00163 // to deal with that. 00164 # ifndef _STLP_INTERNAL_CTIME 00165 # include <stl/_ctime.h> 00166 # endif 00167 # if defined (_STLP_USE_NAMESPACES) && ! defined (_STLP_VENDOR_GLOBAL_CSTD) 00168 using _STLP_VENDOR_CSTD::time_t; 00169 # endif 00170 # include <synch.h> 00171 # ifndef _STLP_INTERNAL_CSTDIO 00172 # include <stl/_cstdio.h> 00173 # endif 00174 # ifndef _STLP_INTERNAL_CWCHAR 00175 # include <stl/_cwchar.h> 00176 # endif 00177 typedef size_t __stl_atomic_t; 00178 00179 # elif defined (_STLP_BETHREADS) 00180 00181 # include <OS.h> 00182 # include <cassert> 00183 # include <stdio.h> 00184 # define _STLP_MUTEX_INITIALIZER = { 0 } 00185 typedef size_t __stl_atomic_t; 00186 00187 # elif defined (_STLP_NWTHREADS) 00188 00189 # include <nwthread.h> 00190 # include <nwsemaph.h> 00191 typedef size_t __stl_atomic_t; 00192 00193 # elif defined(_STLP_OS2THREADS) 00194 00195 # if defined (__GNUC__) 00196 # define INCL_DOSSEMAPHORES 00197 # include <os2.h> 00198 # else 00199 // This section serves to replace os2.h for VisualAge C++ 00200 typedef unsigned long ULONG; 00201 # if !defined (__HEV__) /* INCL_SEMAPHORE may also define HEV */ 00202 # define __HEV__ 00203 typedef ULONG HEV; 00204 typedef HEV* PHEV; 00205 # endif 00206 typedef ULONG APIRET; 00207 typedef ULONG HMTX; 00208 typedef HMTX* PHMTX; 00209 typedef const char* PCSZ; 00210 typedef ULONG BOOL32; 00211 APIRET _System DosCreateMutexSem(PCSZ pszName, PHEV phev, ULONG flAttr, BOOL32 fState); 00212 APIRET _System DosRequestMutexSem(HMTX hmtx, ULONG ulTimeout); 00213 APIRET _System DosReleaseMutexSem(HMTX hmtx); 00214 APIRET _System DosCloseMutexSem(HMTX hmtx); 00215 # define _STLP_MUTEX_INITIALIZER = { 0 } 00216 # endif /* GNUC */ 00217 typedef size_t __stl_atomic_t; 00218 00219 # else 00220 00221 typedef size_t __stl_atomic_t; 00222 00223 # endif 00224 00225 #else 00226 /* no threads */ 00227 # define _STLP_ATOMIC_INCREMENT(__x) ++(*__x) 00228 # define _STLP_ATOMIC_DECREMENT(__x) --(*__x) 00229 /* We do not grant other atomic operations as they are useless if STLport do not have 00230 * to be thread safe 00231 */ 00232 typedef size_t __stl_atomic_t; 00233 #endif 00234 00235 #if !defined (_STLP_MUTEX_INITIALIZER) 00236 # if defined(_STLP_ATOMIC_EXCHANGE) 00237 # define _STLP_MUTEX_INITIALIZER = { 0 } 00238 # elif defined(_STLP_UITHREADS) 00239 # define _STLP_MUTEX_INITIALIZER = { DEFAULTMUTEX } 00240 # else 00241 # define _STLP_MUTEX_INITIALIZER 00242 # endif 00243 #endif 00244 00245 _STLP_BEGIN_NAMESPACE 00246 00247 #if defined (_STLP_THREADS) && !defined (_STLP_USE_PTHREAD_SPINLOCK) 00248 // Helper struct. This is a workaround for various compilers that don't 00249 // handle static variables in inline functions properly. 00250 template <int __inst> 00251 struct _STLP_mutex_spin { 00252 enum { __low_max = 30, __high_max = 1000 }; 00253 // Low if we suspect uniprocessor, high for multiprocessor. 00254 static unsigned __max; 00255 static unsigned __last; 00256 static void _STLP_CALL _M_do_lock(volatile __stl_atomic_t* __lock); 00257 static void _STLP_CALL _S_nsec_sleep(int __log_nsec, unsigned int& __iteration); 00258 }; 00259 #endif // !_STLP_USE_PTHREAD_SPINLOCK 00260 00261 // Locking class. Note that this class *does not have a constructor*. 00262 // It must be initialized either statically, with _STLP_MUTEX_INITIALIZER, 00263 // or dynamically, by explicitly calling the _M_initialize member function. 00264 // (This is similar to the ways that a pthreads mutex can be initialized.) 00265 // There are explicit member functions for acquiring and releasing the lock. 00266 00267 // There is no constructor because static initialization is essential for 00268 // some uses, and only a class aggregate (see section 8.5.1 of the C++ 00269 // standard) can be initialized that way. That means we must have no 00270 // constructors, no base classes, no virtual functions, and no private or 00271 // protected members. 00272 00273 // For non-static cases, clients should use _STLP_mutex. 00274 00275 struct _STLP_CLASS_DECLSPEC _STLP_mutex_base { 00276 #if defined (_STLP_ATOMIC_EXCHANGE) || defined (_STLP_SGI_THREADS) 00277 // It should be relatively easy to get this to work on any modern Unix. 00278 volatile __stl_atomic_t _M_lock; 00279 #endif 00280 00281 #if defined (_STLP_THREADS) 00282 # if defined (_STLP_ATOMIC_EXCHANGE) 00283 inline void _M_initialize() { _M_lock = 0; } 00284 inline void _M_destroy() {} 00285 00286 void _M_acquire_lock() { 00287 _STLP_mutex_spin<0>::_M_do_lock(&_M_lock); 00288 } 00289 00290 inline void _M_release_lock() { 00291 volatile __stl_atomic_t* __lock = &_M_lock; 00292 # if defined(_STLP_SGI_THREADS) && defined(__GNUC__) && __mips >= 3 00293 asm("sync"); 00294 *__lock = 0; 00295 # elif defined(_STLP_SGI_THREADS) && __mips >= 3 && \ 00296 (defined (_ABIN32) || defined(_ABI64)) 00297 __lock_release(__lock); 00298 # elif defined (_STLP_SPARC_SOLARIS_THREADS) 00299 # if defined (__WORD64) || defined (__arch64__) || defined (__sparcv9) || defined (__sparcv8plus) 00300 asm("membar #StoreStore ; membar #LoadStore"); 00301 # else 00302 asm(" stbar "); 00303 # endif 00304 *__lock = 0; 00305 # else 00306 *__lock = 0; 00307 // This is not sufficient on many multiprocessors, since 00308 // writes to protected variables and the lock may be reordered. 00309 # endif 00310 } 00311 # elif defined (_STLP_PTHREADS) 00312 # if defined (_STLP_USE_PTHREAD_SPINLOCK) 00313 # if !defined (__OpenBSD__) 00314 pthread_spinlock_t _M_lock; 00315 inline void _M_initialize() { pthread_spin_init( &_M_lock, 0 ); } 00316 inline void _M_destroy() { pthread_spin_destroy( &_M_lock ); } 00317 00318 // sorry, but no static initializer for pthread_spinlock_t; 00319 // this will not work for compilers that has problems with call 00320 // constructor of static object... 00321 00322 // _STLP_mutex_base() 00323 // { pthread_spin_init( &_M_lock, 0 ); } 00324 00325 // ~_STLP_mutex_base() 00326 // { pthread_spin_destroy( &_M_lock ); } 00327 00328 inline void _M_acquire_lock() { pthread_spin_lock( &_M_lock ); } 00329 inline void _M_release_lock() { pthread_spin_unlock( &_M_lock ); } 00330 # else // __OpenBSD__ 00331 spinlock_t _M_lock; 00332 inline void _M_initialize() { _SPINLOCK_INIT( &_M_lock ); } 00333 inline void _M_destroy() { } 00334 inline void _M_acquire_lock() { _SPINLOCK( &_M_lock ); } 00335 inline void _M_release_lock() { _SPINUNLOCK( &_M_lock ); } 00336 # endif // __OpenBSD__ 00337 # else // !_STLP_USE_PTHREAD_SPINLOCK 00338 pthread_mutex_t _M_lock; 00339 inline void _M_initialize() 00340 { pthread_mutex_init(&_M_lock,_STLP_PTHREAD_ATTR_DEFAULT); } 00341 inline void _M_destroy() 00342 { pthread_mutex_destroy(&_M_lock); } 00343 inline void _M_acquire_lock() { 00344 # if defined ( __hpux ) && ! defined (PTHREAD_MUTEX_INITIALIZER) 00345 if (!_M_lock.field1) _M_initialize(); 00346 # endif 00347 pthread_mutex_lock(&_M_lock); 00348 } 00349 inline void _M_release_lock() { pthread_mutex_unlock(&_M_lock); } 00350 # endif // !_STLP_USE_PTHREAD_SPINLOCK 00351 00352 # elif defined (_STLP_UITHREADS) 00353 mutex_t _M_lock; 00354 inline void _M_initialize() 00355 { mutex_init(&_M_lock, 0, NULL); } 00356 inline void _M_destroy() 00357 { mutex_destroy(&_M_lock); } 00358 inline void _M_acquire_lock() { mutex_lock(&_M_lock); } 00359 inline void _M_release_lock() { mutex_unlock(&_M_lock); } 00360 00361 # elif defined (_STLP_OS2THREADS) 00362 HMTX _M_lock; 00363 inline void _M_initialize() { DosCreateMutexSem(NULL, &_M_lock, 0, false); } 00364 inline void _M_destroy() { DosCloseMutexSem(_M_lock); } 00365 inline void _M_acquire_lock() { 00366 if (!_M_lock) _M_initialize(); 00367 DosRequestMutexSem(_M_lock, SEM_INDEFINITE_WAIT); 00368 } 00369 inline void _M_release_lock() { DosReleaseMutexSem(_M_lock); } 00370 # elif defined (_STLP_BETHREADS) 00371 sem_id sem; 00372 inline void _M_initialize() { 00373 sem = create_sem(1, "STLPort"); 00374 assert(sem > 0); 00375 } 00376 inline void _M_destroy() { 00377 int t = delete_sem(sem); 00378 assert(t == B_NO_ERROR); 00379 } 00380 inline void _M_acquire_lock(); 00381 inline void _M_release_lock() { 00382 status_t t = release_sem(sem); 00383 assert(t == B_NO_ERROR); 00384 } 00385 # elif defined (_STLP_NWTHREADS) 00386 LONG _M_lock; 00387 inline void _M_initialize() 00388 { _M_lock = OpenLocalSemaphore(1); } 00389 inline void _M_destroy() 00390 { CloseLocalSemaphore(_M_lock); } 00391 inline void _M_acquire_lock() 00392 { WaitOnLocalSemaphore(_M_lock); } 00393 inline void _M_release_lock() { SignalLocalSemaphore(_M_lock); } 00394 # else //*ty 11/24/2001 - added configuration check 00395 # error "Unknown thread facility configuration" 00396 # endif 00397 #else /* No threads */ 00398 inline void _M_initialize() {} 00399 inline void _M_destroy() {} 00400 inline void _M_acquire_lock() {} 00401 inline void _M_release_lock() {} 00402 #endif // _STLP_PTHREADS 00403 }; 00404 00405 // Locking class. The constructor initializes the lock, the destructor destroys it. 00406 // Well - behaving class, does not need static initializer 00407 00408 class _STLP_CLASS_DECLSPEC _STLP_mutex : public _STLP_mutex_base { 00409 public: 00410 inline _STLP_mutex () { _M_initialize(); } 00411 inline ~_STLP_mutex () { _M_destroy(); } 00412 private: 00413 _STLP_mutex(const _STLP_mutex&); 00414 void operator=(const _STLP_mutex&); 00415 }; 00416 00417 // A locking class that uses _STLP_STATIC_MUTEX. The constructor takes 00418 // a reference to an _STLP_STATIC_MUTEX, and acquires a lock. The destructor 00419 // releases the lock. 00420 // It's not clear that this is exactly the right functionality. 00421 // It will probably change in the future. 00422 00423 struct _STLP_CLASS_DECLSPEC _STLP_auto_lock { 00424 _STLP_auto_lock(_STLP_STATIC_MUTEX& __lock) : _M_lock(__lock) 00425 { _M_lock._M_acquire_lock(); } 00426 ~_STLP_auto_lock() 00427 { _M_lock._M_release_lock(); } 00428 00429 private: 00430 _STLP_STATIC_MUTEX& _M_lock; 00431 void operator=(const _STLP_auto_lock&); 00432 _STLP_auto_lock(const _STLP_auto_lock&); 00433 }; 00434 00435 /* 00436 * Class _Refcount_Base provides a type, __stl_atomic_t, a data member, 00437 * _M_ref_count, and member functions _M_incr and _M_decr, which perform 00438 * atomic preincrement/predecrement. The constructor initializes 00439 * _M_ref_count. 00440 */ 00441 class _STLP_CLASS_DECLSPEC _Refcount_Base { 00442 // The data member _M_ref_count 00443 #if defined (__DMC__) 00444 public: 00445 #endif 00446 _STLP_VOLATILE __stl_atomic_t _M_ref_count; 00447 00448 #if defined (_STLP_THREADS) && \ 00449 (!defined (_STLP_ATOMIC_INCREMENT) || !defined (_STLP_ATOMIC_DECREMENT) || \ 00450 defined (_STLP_WIN95_LIKE)) 00451 # define _STLP_USE_MUTEX 00452 _STLP_mutex _M_mutex; 00453 #endif 00454 00455 public: 00456 // Constructor 00457 _Refcount_Base(__stl_atomic_t __n) : _M_ref_count(__n) {} 00458 #if defined (__BORLANDC__) 00459 ~_Refcount_Base(){}; 00460 #endif 00461 00462 // _M_incr and _M_decr 00463 #if defined (_STLP_THREADS) 00464 # if !defined (_STLP_USE_MUTEX) 00465 __stl_atomic_t _M_incr() { return _STLP_ATOMIC_INCREMENT(&_M_ref_count); } 00466 __stl_atomic_t _M_decr() { return _STLP_ATOMIC_DECREMENT(&_M_ref_count); } 00467 # else 00468 # undef _STLP_USE_MUTEX 00469 __stl_atomic_t _M_incr() { 00470 _STLP_auto_lock l(_M_mutex); 00471 return ++_M_ref_count; 00472 } 00473 __stl_atomic_t _M_decr() { 00474 _STLP_auto_lock l(_M_mutex); 00475 return --_M_ref_count; 00476 } 00477 # endif 00478 #else /* No threads */ 00479 __stl_atomic_t _M_incr() { return ++_M_ref_count; } 00480 __stl_atomic_t _M_decr() { return --_M_ref_count; } 00481 #endif 00482 }; 00483 00484 /* Atomic swap on __stl_atomic_t 00485 * This is guaranteed to behave as though it were atomic only if all 00486 * possibly concurrent updates use _Atomic_swap. 00487 * In some cases the operation is emulated with a lock. 00488 * Idem for _Atomic_swap_ptr 00489 */ 00490 /* Helper struct to handle following cases: 00491 * - on platforms where sizeof(__stl_atomic_t) == sizeof(void*) atomic 00492 * exchange can be done on pointers 00493 * - on platform without atomic operation swap is done in a critical section, 00494 * portable but inefficient. 00495 */ 00496 template <int __use_ptr_atomic_swap> 00497 class _Atomic_swap_struct { 00498 public: 00499 #if defined (_STLP_THREADS) && \ 00500 !defined (_STLP_ATOMIC_EXCHANGE) && \ 00501 (defined (_STLP_PTHREADS) || defined (_STLP_UITHREADS) || defined (_STLP_OS2THREADS) || \ 00502 defined (_STLP_USE_PTHREAD_SPINLOCK) || defined (_STLP_NWTHREADS)) 00503 # define _STLP_USE_ATOMIC_SWAP_MUTEX 00504 static _STLP_STATIC_MUTEX _S_swap_lock; 00505 #endif 00506 00507 static __stl_atomic_t _S_swap(_STLP_VOLATILE __stl_atomic_t* __p, __stl_atomic_t __q) { 00508 #if defined (_STLP_THREADS) 00509 # if defined (_STLP_ATOMIC_EXCHANGE) 00510 return _STLP_ATOMIC_EXCHANGE(__p, __q); 00511 # elif defined (_STLP_USE_ATOMIC_SWAP_MUTEX) 00512 _S_swap_lock._M_acquire_lock(); 00513 __stl_atomic_t __result = *__p; 00514 *__p = __q; 00515 _S_swap_lock._M_release_lock(); 00516 return __result; 00517 # else 00518 # error Missing atomic swap implementation 00519 # endif 00520 #else 00521 /* no threads */ 00522 __stl_atomic_t __result = *__p; 00523 *__p = __q; 00524 return __result; 00525 #endif // _STLP_THREADS 00526 } 00527 00528 static void* _S_swap_ptr(void* _STLP_VOLATILE* __p, void* __q) { 00529 #if defined (_STLP_THREADS) 00530 # if defined (_STLP_ATOMIC_EXCHANGE_PTR) 00531 return _STLP_ATOMIC_EXCHANGE_PTR(__p, __q); 00532 # elif defined (_STLP_ATOMIC_EXCHANGE) 00533 _STLP_STATIC_ASSERT(sizeof(__stl_atomic_t) == sizeof(void*)) 00534 return __REINTERPRET_CAST(void*, _STLP_ATOMIC_EXCHANGE(__REINTERPRET_CAST(volatile __stl_atomic_t*, __p), 00535 __REINTERPRET_CAST(__stl_atomic_t, __q)) 00536 ); 00537 # elif defined (_STLP_USE_ATOMIC_SWAP_MUTEX) 00538 _S_swap_lock._M_acquire_lock(); 00539 void *__result = *__p; 00540 *__p = __q; 00541 _S_swap_lock._M_release_lock(); 00542 return __result; 00543 # else 00544 # error Missing pointer atomic swap implementation 00545 # endif 00546 #else 00547 /* no thread */ 00548 void *__result = *__p; 00549 *__p = __q; 00550 return __result; 00551 #endif 00552 } 00553 }; 00554 00555 _STLP_TEMPLATE_NULL 00556 class _Atomic_swap_struct<0> { 00557 public: 00558 #if defined (_STLP_THREADS) && \ 00559 (!defined (_STLP_ATOMIC_EXCHANGE) || !defined (_STLP_ATOMIC_EXCHANGE_PTR)) && \ 00560 (defined (_STLP_PTHREADS) || defined (_STLP_UITHREADS) || defined (_STLP_OS2THREADS) || \ 00561 defined (_STLP_USE_PTHREAD_SPINLOCK) || defined (_STLP_NWTHREADS)) 00562 # define _STLP_USE_ATOMIC_SWAP_MUTEX 00563 static _STLP_STATIC_MUTEX _S_swap_lock; 00564 #endif 00565 00566 static __stl_atomic_t _S_swap(_STLP_VOLATILE __stl_atomic_t* __p, __stl_atomic_t __q) { 00567 #if defined (_STLP_THREADS) 00568 # if defined (_STLP_ATOMIC_EXCHANGE) 00569 return _STLP_ATOMIC_EXCHANGE(__p, __q); 00570 # elif defined (_STLP_USE_ATOMIC_SWAP_MUTEX) 00571 /* This should be portable, but performance is expected 00572 * to be quite awful. This really needs platform specific 00573 * code. 00574 */ 00575 _S_swap_lock._M_acquire_lock(); 00576 __stl_atomic_t __result = *__p; 00577 *__p = __q; 00578 _S_swap_lock._M_release_lock(); 00579 return __result; 00580 # else 00581 # error Missing atomic swap implementation 00582 # endif 00583 #else 00584 /* no threads */ 00585 __stl_atomic_t __result = *__p; 00586 *__p = __q; 00587 return __result; 00588 #endif // _STLP_THREADS 00589 } 00590 00591 static void* _S_swap_ptr(void* _STLP_VOLATILE* __p, void* __q) { 00592 #if defined (_STLP_THREADS) 00593 # if defined (_STLP_ATOMIC_EXCHANGE_PTR) 00594 return _STLP_ATOMIC_EXCHANGE_PTR(__p, __q); 00595 # elif defined (_STLP_ATOMIC_EXCHANGE) 00596 _STLP_STATIC_ASSERT(sizeof(__stl_atomic_t) == sizeof(void*)) 00597 return __REINTERPRET_CAST(void*, _STLP_ATOMIC_EXCHANGE(__REINTERPRET_CAST(volatile __stl_atomic_t*, __p), 00598 __REINTERPRET_CAST(__stl_atomic_t, __q)) 00599 ); 00600 # elif defined (_STLP_USE_ATOMIC_SWAP_MUTEX) 00601 _S_swap_lock._M_acquire_lock(); 00602 void *__result = *__p; 00603 *__p = __q; 00604 _S_swap_lock._M_release_lock(); 00605 return __result; 00606 # else 00607 # error Missing pointer atomic swap implementation 00608 # endif 00609 #else 00610 /* no thread */ 00611 void *__result = *__p; 00612 *__p = __q; 00613 return __result; 00614 #endif 00615 } 00616 }; 00617 00618 #if defined (_STLP_MSVC) && (_STLP_MSVC == 1300) 00619 # pragma warning (push) 00620 # pragma warning (disable : 4189) //__use_ptr_atomic_swap initialized but not used 00621 #endif 00622 00623 inline __stl_atomic_t _STLP_CALL _Atomic_swap(_STLP_VOLATILE __stl_atomic_t * __p, __stl_atomic_t __q) { 00624 const int __use_ptr_atomic_swap = sizeof(__stl_atomic_t) == sizeof(void*); 00625 return _Atomic_swap_struct<__use_ptr_atomic_swap>::_S_swap(__p, __q); 00626 } 00627 00628 inline void* _STLP_CALL _Atomic_swap_ptr(void* _STLP_VOLATILE* __p, void* __q) { 00629 const int __use_ptr_atomic_swap = sizeof(__stl_atomic_t) == sizeof(void*); 00630 return _Atomic_swap_struct<__use_ptr_atomic_swap>::_S_swap_ptr(__p, __q); 00631 } 00632 00633 #if defined (_STLP_MSVC) && (_STLP_MSVC == 1300) 00634 # pragma warning (pop) 00635 #endif 00636 00637 #if defined (_STLP_BETHREADS) 00638 template <int __inst> 00639 struct _STLP_beos_static_lock_data { 00640 static bool is_init; 00641 struct mutex_t : public _STLP_mutex { 00642 mutex_t() 00643 { _STLP_beos_static_lock_data<0>::is_init = true; } 00644 ~mutex_t() 00645 { _STLP_beos_static_lock_data<0>::is_init = false; } 00646 }; 00647 static mutex_t mut; 00648 }; 00649 00650 template <int __inst> 00651 bool _STLP_beos_static_lock_data<__inst>::is_init = false; 00652 template <int __inst> 00653 typename _STLP_beos_static_lock_data<__inst>::mutex_t _STLP_beos_static_lock_data<__inst>::mut; 00654 00655 inline void _STLP_mutex_base::_M_acquire_lock() { 00656 if (sem == 0) { 00657 // we need to initialise on demand here 00658 // to prevent race conditions use our global 00659 // mutex if it's available: 00660 if (_STLP_beos_static_lock_data<0>::is_init) { 00661 _STLP_auto_lock al(_STLP_beos_static_lock_data<0>::mut); 00662 if (sem == 0) _M_initialize(); 00663 } 00664 else { 00665 // no lock available, we must still be 00666 // in startup code, THERE MUST BE ONE THREAD 00667 // ONLY active at this point. 00668 _M_initialize(); 00669 } 00670 } 00671 status_t t; 00672 t = acquire_sem(sem); 00673 assert(t == B_NO_ERROR); 00674 } 00675 #endif 00676 00677 _STLP_END_NAMESPACE 00678 00679 #if !defined (_STLP_LINK_TIME_INSTANTIATION) 00680 # include <stl/_threads.c> 00681 #endif 00682 00683 #endif /* _STLP_INTERNAL_THREADS_H */ 00684 00685 // Local Variables: 00686 // mode:C++ 00687 // End: Generated on Sun May 27 2012 04:29:38 for ReactOS by
1.7.6.1
|