_threads.h

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 // Stl_config.h should be included before this file.
00023 
00024 
00025 #ifndef _STLP_INTERNAL_THREADS_H
00026 #define _STLP_INTERNAL_THREADS_H
00027 
00028 // Supported threading models are native SGI, pthreads, uithreads
00029 // (similar to pthreads, but based on an earlier draft of the Posix
00030 // threads standard), and Win32 threads.  Uithread support by Jochen
00031 // Schlick, 1999, and Solaris threads generalized to them.
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 // On SUN and Mac OS X gcc, zero-initialization works just fine...
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 // Hack for SGI o32 compilers.
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 /* o32 */
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 //HPUX variants have (on some platforms optional) non-standard "DCE" pthreads impl
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 // This section serves as a replacement for windows.h header for Visual C++
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   // boris : for the latest SDK, you may actually need the other version of the declaration (above)
00121   // even for earlier VC++ versions. There is no way to tell SDK versions apart, sorry ...
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 } /* extern "C" */
00136 
00137 #   endif /* STL_MSVC */
00138 
00139 #   define _STLP_WINDOWS_H_INCLUDED
00140 
00141 #  endif /* _WINDOWS_ */
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 // this inclusion is potential hazard to bring up all sorts
00157 // of old-style headers. Let's assume vendor already know how
00158 // to deal with that.
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   // This section serves to replace os2.h for VisualAge C++
00173   typedef unsigned long ULONG;
00174   #ifndef __HEV__  /* INCL_SEMAPHORE may also define 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 // Helper struct.  This is a workaround for various compilers that don't
00205 // handle static variables in inline functions properly.
00206 template <int __inst>
00207 struct _STLP_mutex_spin {
00208   enum { __low_max = 30, __high_max = 1000 };
00209   // Low if we suspect uniprocessor, high for multiprocessor.
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 // Locking class.  Note that this class *does not have a constructor*.
00218 // It must be initialized either statically, with _STLP_MUTEX_INITIALIZER,
00219 // or dynamically, by explicitly calling the _M_initialize member function.
00220 // (This is similar to the ways that a pthreads mutex can be initialized.)
00221 // There are explicit member functions for acquiring and releasing the lock.
00222 
00223 // There is no constructor because static initialization is essential for
00224 // some uses, and only a class aggregate (see section 8.5.1 of the C++
00225 // standard) can be initialized that way.  That means we must have no
00226 // constructors, no base classes, no virtual functions, and no private or
00227 // protected members.
00228 
00229 // For non-static cases, clients should use  _STLP_mutex.
00230 
00231 struct _STLP_CLASS_DECLSPEC _STLP_mutex_base
00232 {
00233 #if defined(_STLP_ATOMIC_EXCHANGE) || defined(_STLP_SGI_THREADS)
00234   // It should be relatively easy to get this to work on any modern Unix.
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         // This is not sufficient on many multiprocessors, since
00267         // writes to protected variables and the lock may be reordered.
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 /* No threads */
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 // This class could be just a smart pointer, but we do want to keep 
00336 // WIN32 optimized at a maximum
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 /* No threads */
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 // Locking class.  The constructor initializes the lock, the destructor destroys it.
00394 // Well - behaving class, does not need static initializer
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 // Class _Refcount_Base provides a type, __stl_atomic_t, a data member,
00409 // _M_ref_count, and member functions _M_incr and _M_decr, which perform
00410 // atomic preincrement/predecrement.  The constructor initializes 
00411 // _M_ref_count.
00412 struct _STLP_CLASS_DECLSPEC _Refcount_Base
00413 {
00414   // The data member _M_ref_count
00415   volatile __stl_atomic_t _M_ref_count;
00416 
00417 # if !defined (_STLP_ATOMIC_EXCHANGE)
00418   _STLP_mutex _M_mutex;
00419 # endif
00420 
00421   // Constructor
00422   _Refcount_Base(__stl_atomic_t __n) : _M_ref_count(__n) {}
00423 
00424   // _M_incr and _M_decr
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  /* No threads */
00440   void _M_incr() { ++_M_ref_count; }
00441   void _M_decr() { --_M_ref_count; }
00442 # endif
00443 };
00444 
00445 // Atomic swap on unsigned long
00446 // This is guaranteed to behave as though it were atomic only if all
00447 // possibly concurrent updates use _Atomic_swap.
00448 // In some cases the operation is emulated with a lock.
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 // We use a template here only to get a unique initialized instance.
00455 template<int __dummy>
00456 struct _Swap_lock_struct {
00457   static _STLP_STATIC_MUTEX _S_swap_lock;
00458 };
00459 
00460 
00461 // This should be portable, but performance is expected
00462 // to be quite awful.  This really needs platform specific
00463 // code.
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 /* no threads */
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 // A locking class that uses _STLP_STATIC_MUTEX.  The constructor takes
00482 // a reference to an _STLP_STATIC_MUTEX, and acquires a lock.  The destructor
00483 // releases the lock.
00484 // It's not clear that this is exactly the right functionality.
00485 // It will probably change in the future.
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                 // we need to initialise on demand here
00533                 // to prevent race conditions use our global
00534                 // mutex if it's available:
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                         // no lock available, we must still be
00543                         // in startup code, THERE MUST BE ONE THREAD
00544                         // ONLY active at this point.
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 /* _STLP_INTERNAL_THREADS_H */
00562 
00563 // Local Variables:
00564 // mode:C++
00565 // End:

Generated on Mon Jun 5 10:20:47 2006 for Intelligence.kdevelop by  doxygen 1.4.6