epoc32/include/stdapis/stlport/stl/_threads.h
branchSymbian2
changeset 2 2fe1408b6811
parent 0 061f57f2323e
equal deleted inserted replaced
1:666f914201fb 2:2fe1408b6811
     1 _threads.h
     1 /*
       
     2  * Copyright (c) 1997-1999
       
     3  * Silicon Graphics Computer Systems, Inc.
       
     4  *
       
     5  * Copyright (c) 1999 
       
     6  * Boris Fomitchev
       
     7  *
       
     8  * This material is provided "as is", with absolutely no warranty expressed
       
     9  * or implied. Any use is at your own risk.
       
    10  *
       
    11  * Permission to use or copy this software for any purpose is hereby granted 
       
    12  * without fee, provided the above notices are retained on all copies.
       
    13  * Permission to modify the code and to distribute modified code is granted,
       
    14  * provided the above notices are retained, and a notice that the code was
       
    15  * modified is included with the above copyright notice.
       
    16  *
       
    17  */
       
    18 
       
    19 // WARNING: This is an internal header file, included by other C++
       
    20 // standard library headers.  You should not attempt to use this header
       
    21 // file directly.
       
    22 // Stl_config.h should be included before this file.
       
    23 
       
    24 
       
    25 #ifndef _STLP_INTERNAL_THREADS_H
       
    26 #define _STLP_INTERNAL_THREADS_H
       
    27 
       
    28 // Supported threading models are native SGI, pthreads, uithreads
       
    29 // (similar to pthreads, but based on an earlier draft of the Posix
       
    30 // threads standard), and Win32 threads.  Uithread support by Jochen
       
    31 // Schlick, 1999, and Solaris threads generalized to them.
       
    32 
       
    33 #ifndef _STLP_CONFIG_H
       
    34 #include <stl/_config.h>
       
    35 #endif
       
    36 
       
    37 # if ! defined (_STLP_CSTDDEF)
       
    38 #  include <cstddef>
       
    39 # endif
       
    40 
       
    41 # if ! defined (_STLP_CSTDLIB)
       
    42 #  include <cstdlib>
       
    43 # endif
       
    44 
       
    45 // On SUN and Mac OS X gcc, zero-initialization works just fine...
       
    46 # if defined (__sun) || ( defined(__GNUC__) && defined(__APPLE__) )
       
    47 # define _STLP_MUTEX_INITIALIZER
       
    48 # endif
       
    49 
       
    50 # if defined (_STLP_WIN32) || defined (__sgi) || defined (_STLP_SPARC_SOLARIS_THREADS)
       
    51   typedef long __stl_atomic_t;
       
    52 # else 
       
    53 # if defined (_STLP_USE_NAMESPACES) && ! defined (_STLP_VENDOR_GLOBAL_CSTD)
       
    54 // using _STLP_VENDOR_CSTD::size_t;
       
    55 using namespace _STLP_VENDOR_CSTD;
       
    56 # endif
       
    57   typedef size_t __stl_atomic_t;
       
    58 #endif  
       
    59 
       
    60 # if defined(_STLP_SGI_THREADS)
       
    61 #  include <mutex.h>
       
    62 // Hack for SGI o32 compilers.
       
    63 #if !defined(__add_and_fetch) && \
       
    64     (__mips < 3 || !(defined (_ABIN32) || defined(_ABI64)))
       
    65 #  define __add_and_fetch(__l,__v) add_then_test((unsigned long*)__l,__v)  
       
    66 #  define __test_and_set(__l,__v)  test_and_set(__l,__v)
       
    67 #endif /* o32 */
       
    68 
       
    69 # if __mips < 3 || !(defined (_ABIN32) || defined(_ABI64))
       
    70 #  define _STLP_ATOMIC_EXCHANGE(__p, __q) test_and_set(__p, __q)
       
    71 # else
       
    72 #  define _STLP_ATOMIC_EXCHANGE(__p, __q) __test_and_set((unsigned long*)__p, (unsigned long)__q)
       
    73 # endif
       
    74 
       
    75 #  define _STLP_ATOMIC_INCREMENT(__x) __add_and_fetch(__x, 1)
       
    76 #  define _STLP_ATOMIC_DECREMENT(__x) __add_and_fetch(__x, (size_t) -1)
       
    77 
       
    78 # elif defined (__GNUC__) && defined (__i386__) && defined (__unix__) && defined (_STLP_USE_INLINE_X86_SPINLOCK) 
       
    79 
       
    80 // gcc on i386 linux, freebsd, etc. 
       
    81 
       
    82 // This enables the memory caching on x86 linux.  It is critical for SMP
       
    83 // without it the performace is DISMAL!
       
    84 static inline unsigned long __xchg(volatile __stl_atomic_t* target, int source)
       
    85 {
       
    86 
       
    87   // The target is refernce in memory rather than the register
       
    88   // because making a copy of it from memory to the register and
       
    89   // back again would ruin the atomic nature of the call.
       
    90   // the source does not need to be delt with atomicly so it can
       
    91   // be copied about as needed.
       
    92   //
       
    93   // The casting of the source is used to prevent gcc from optimizing 
       
    94   // in such a way that breaks the atomic nature of this call.
       
    95   //
       
    96   __asm__ __volatile__("xchgl %1,%0"
       
    97 		       :"=m" (*(volatile long *) target), "=r" (source)
       
    98 		       :"m" (*(volatile long *) target), "r" (source) );
       
    99   return source;
       
   100 
       
   101   //  The assembly above does the following atomicly:
       
   102   //   int temp=source;
       
   103   //   source=(int)(*target);
       
   104   //   (int)(*target)=temp;
       
   105   // return source
       
   106 }
       
   107 
       
   108 static inline void __inc_and_fetch(volatile __stl_atomic_t* __x)
       
   109 {
       
   110   // Referenced in memory rather than register to preserve the atomic nature.
       
   111   //
       
   112   __asm__ __volatile__(
       
   113       "lock; incl %0"
       
   114       :"=m" (*__x)
       
   115       :"m" (*__x) );
       
   116 
       
   117   //  The assembly above does the following atomicly:
       
   118   //   ++(int)(*__x);
       
   119 
       
   120 }
       
   121 static inline void __dec_and_fetch(volatile __stl_atomic_t* __x)
       
   122 {
       
   123   // Referenced in memory rather than register to preserve the atomic nature.
       
   124   //
       
   125   __asm__ __volatile__(
       
   126       "lock; decl %0"
       
   127       :"=m" (*__x)
       
   128       :"m" (*__x) );
       
   129 
       
   130   //  The assembly above does the following atomicly:
       
   131   //   --(int)(*__x);
       
   132 }
       
   133 
       
   134 #  define _STLP_ATOMIC_EXCHANGE(target, newValue) ((__xchg(target, newValue)))
       
   135 #  define _STLP_ATOMIC_INCREMENT(__x) __inc_and_fetch(__x)
       
   136 #  define _STLP_ATOMIC_DECREMENT(__x) __dec_and_fetch(__x)
       
   137 
       
   138 # elif defined(_STLP_PTHREADS)
       
   139 
       
   140 #  include <pthread.h>
       
   141 #  ifndef _STLP_USE_PTHREAD_SPINLOCK
       
   142 #   if defined(PTHREAD_MUTEX_INITIALIZER) && !defined(_STLP_MUTEX_INITIALIZER)
       
   143 #    define _STLP_MUTEX_INITIALIZER = { PTHREAD_MUTEX_INITIALIZER }
       
   144 #   endif
       
   145 
       
   146 //HPUX variants have (on some platforms optional) non-standard "DCE" pthreads impl
       
   147 #   if defined(_DECTHREADS_) && (defined(_PTHREAD_USE_D4) || defined(__hpux)) && !defined(_CMA_SUPPRESS_EXTERNALS_)
       
   148 #    define _STLP_PTHREAD_ATTR_DEFAULT pthread_mutexattr_default
       
   149 #   else
       
   150 #    define _STLP_PTHREAD_ATTR_DEFAULT 0
       
   151 #   endif
       
   152 #  endif // !_STLP_USE_PTHREAD_SPINLOCK 
       
   153 
       
   154 # elif defined(_STLP_WIN32THREADS)
       
   155 #  if !defined (_STLP_WINDOWS_H_INCLUDED) && ! defined (_WINDOWS_H)
       
   156 #   if ! (defined ( _STLP_MSVC ) || defined (__BORLANDC__) || defined (__ICL) || defined (__WATCOMC__) || defined (__MINGW32__) || defined (__DMC__))
       
   157 #    ifdef _STLP_USE_MFC
       
   158 #     include <afx.h>
       
   159 #    else
       
   160 #     include <windows.h>
       
   161 #    endif
       
   162 #    define _STLP_WINDOWS_H_INCLUDED
       
   163 #   else 
       
   164 // This section serves as a replacement for windows.h header for Visual C++
       
   165 extern "C" {
       
   166 #   if (defined(_M_MRX000) || defined(_M_ALPHA) \
       
   167        || (defined(_M_PPC) && (_MSC_VER >= 1000))) && !defined(RC_INVOKED)
       
   168 #    define InterlockedIncrement       _InterlockedIncrement
       
   169 #    define InterlockedDecrement       _InterlockedDecrement
       
   170 #    define InterlockedExchange        _InterlockedExchange
       
   171 #    define _STLP_STDCALL
       
   172 #   else
       
   173 #    ifdef _MAC
       
   174 #     define _STLP_STDCALL _cdecl
       
   175 #    else
       
   176 #     define _STLP_STDCALL __stdcall
       
   177 #    endif
       
   178 #   endif
       
   179 
       
   180 #if (_MSC_VER >= 1300) || defined (_STLP_NEW_PLATFORM_SDK)
       
   181 _STLP_IMPORT_DECLSPEC long _STLP_STDCALL InterlockedIncrement(long volatile *);
       
   182 _STLP_IMPORT_DECLSPEC long _STLP_STDCALL InterlockedDecrement(long volatile *);
       
   183 _STLP_IMPORT_DECLSPEC long _STLP_STDCALL InterlockedExchange(long volatile *, long);
       
   184 #else
       
   185   // boris : for the latest SDK, you may actually need the other version of the declaration (above)
       
   186   // even for earlier VC++ versions. There is no way to tell SDK versions apart, sorry ...
       
   187 _STLP_IMPORT_DECLSPEC long _STLP_STDCALL InterlockedIncrement(long*);
       
   188 _STLP_IMPORT_DECLSPEC long _STLP_STDCALL InterlockedDecrement(long*);
       
   189 _STLP_IMPORT_DECLSPEC long _STLP_STDCALL InterlockedExchange(long*, long);
       
   190 #endif
       
   191 
       
   192 _STLP_IMPORT_DECLSPEC void _STLP_STDCALL Sleep(unsigned long);
       
   193 _STLP_IMPORT_DECLSPEC void _STLP_STDCALL OutputDebugStringA( const char* lpOutputString );
       
   194 
       
   195 #ifdef _STLP_DEBUG
       
   196 typedef unsigned long DWORD;
       
   197 _STLP_IMPORT_DECLSPEC DWORD _STLP_STDCALL GetCurrentThreadId();
       
   198 #endif /* _STLP_DEBUG */
       
   199 
       
   200 #    if defined (InterlockedIncrement)
       
   201 #     pragma intrinsic(_InterlockedIncrement)
       
   202 #     pragma intrinsic(_InterlockedDecrement)
       
   203 #     pragma intrinsic(_InterlockedExchange)
       
   204 #    endif
       
   205 } /* extern "C" */
       
   206 
       
   207 #   endif /* STL_MSVC */
       
   208 
       
   209 #   define _STLP_WINDOWS_H_INCLUDED
       
   210 
       
   211 #  endif /* _STLP_WIN32 */
       
   212 
       
   213 #  ifndef _STLP_ATOMIC_INCREMENT
       
   214 #   define _STLP_ATOMIC_INCREMENT(__x)           InterlockedIncrement((long*)__x)
       
   215 #   define _STLP_ATOMIC_DECREMENT(__x)           InterlockedDecrement((long*)__x)
       
   216 #   define _STLP_ATOMIC_EXCHANGE(__x, __y)       InterlockedExchange((long*)__x, (long)__y)
       
   217 #  endif
       
   218 # elif defined(__DECC) || defined(__DECCXX)
       
   219 #  include <machine/builtins.h>
       
   220 #  define _STLP_ATOMIC_EXCHANGE __ATOMIC_EXCH_LONG
       
   221 #  define _STLP_ATOMIC_INCREMENT(__x) __ATOMIC_ADD_LONG(__x, 1)
       
   222 #  define _STLP_ATOMIC_DECREMENT(__x) __ATOMIC_ADD_LONG(__x, -1)
       
   223 # elif defined(_STLP_SPARC_SOLARIS_THREADS)
       
   224 #  include <stl/_sparc_atomic.h>
       
   225 # elif defined (_STLP_UITHREADS)
       
   226 // this inclusion is potential hazard to bring up all sorts
       
   227 // of old-style headers. Let's assume vendor already know how
       
   228 // to deal with that.
       
   229 #  include <ctime>
       
   230 # if defined (_STLP_USE_NAMESPACES) && ! defined (_STLP_VENDOR_GLOBAL_CSTD)
       
   231 using _STLP_VENDOR_CSTD::time_t;
       
   232 # endif
       
   233 #  include <synch.h>
       
   234 #  include <cstdio>
       
   235 #  include <stl/_cwchar.h>
       
   236 # elif defined (_STLP_BETHREADS)
       
   237 #  include <OS.h>
       
   238 #include <cassert>
       
   239 #include <stdio.h>
       
   240 #  define _STLP_MUTEX_INITIALIZER = { 0 }
       
   241 #elif defined(_STLP_OS2THREADS)
       
   242 # ifdef __GNUC__
       
   243 #  define INCL_DOSSEMAPHORES
       
   244 #  include <os2.h>
       
   245 # else
       
   246   // This section serves to replace os2.h for VisualAge C++
       
   247   typedef unsigned long ULONG;
       
   248   #ifndef __HEV__  /* INCL_SEMAPHORE may also define HEV */
       
   249     #define __HEV__
       
   250     typedef ULONG HEV;
       
   251     typedef HEV*  PHEV;
       
   252   #endif
       
   253   typedef ULONG APIRET;
       
   254   typedef ULONG HMTX;
       
   255   typedef HMTX*  PHMTX;
       
   256   typedef const char*  PCSZ;
       
   257   typedef ULONG BOOL32;
       
   258   APIRET _System DosCreateMutexSem(PCSZ pszName, PHEV phev, ULONG flAttr, BOOL32 fState);
       
   259   APIRET _System DosRequestMutexSem(HMTX hmtx, ULONG ulTimeout);
       
   260   APIRET _System DosReleaseMutexSem(HMTX hmtx);
       
   261   APIRET _System DosCloseMutexSem(HMTX hmtx);
       
   262 # define _STLP_MUTEX_INITIALIZER = { 0 };
       
   263 #  endif /* GNUC */
       
   264 # elif defined(_STLP_VXWORKS_THREADS)
       
   265 #  include "semLib.h"
       
   266 # endif
       
   267 
       
   268 # ifndef _STLP_MUTEX_INITIALIZER
       
   269 #   if defined(_STLP_ATOMIC_EXCHANGE)
       
   270 // we are using our own spinlock. 
       
   271 #     define _STLP_MUTEX_INITIALIZER = { 0 }
       
   272 #   elif defined(_STLP_UITHREADS)
       
   273 // known case
       
   274 #     define _STLP_MUTEX_INITIALIZER = { DEFAULTMUTEX }
       
   275 #   else
       
   276 // we do not have static initializer available. therefore, on-demand synchronization is needed.
       
   277 #     define _STLP_MUTEX_INITIALIZER
       
   278 #     define _STLP_MUTEX_NEEDS_ONDEMAND_INITIALIZATION
       
   279 #   endif
       
   280 # endif
       
   281 
       
   282 _STLP_BEGIN_NAMESPACE
       
   283 
       
   284 #ifndef _STLP_USE_PTHREAD_SPINLOCK
       
   285 // Helper struct.  This is a workaround for various compilers that don't
       
   286 // handle static variables in inline functions properly.
       
   287 template <int __inst>
       
   288 struct _STLP_mutex_spin {
       
   289   enum { __low_max = 30, __high_max = 1000 };
       
   290   // Low if we suspect uniprocessor, high for multiprocessor.
       
   291   static unsigned __max;
       
   292   static unsigned __last;
       
   293   static void _STLP_CALL _M_do_lock(volatile __stl_atomic_t* __lock);
       
   294   static void _STLP_CALL _S_nsec_sleep(int __log_nsec);
       
   295 };
       
   296 #endif // !_STLP_USE_PTHREAD_SPINLOCK
       
   297 
       
   298 
       
   299 // Locking class.  Note that this class *does not have a constructor*.
       
   300 // It must be initialized either statically, with _STLP_MUTEX_INITIALIZER,
       
   301 // or dynamically, by explicitly calling the _M_initialize member function.
       
   302 // (This is similar to the ways that a pthreads mutex can be initialized.)
       
   303 // There are explicit member functions for acquiring and releasing the lock.
       
   304 
       
   305 // There is no constructor because static initialization is essential for
       
   306 // some uses, and only a class aggregate (see section 8.5.1 of the C++
       
   307 // standard) can be initialized that way.  That means we must have no
       
   308 // constructors, no base classes, no virtual functions, and no private or
       
   309 // protected members.
       
   310 
       
   311 // For non-static cases, clients should use  _STLP_mutex.
       
   312 
       
   313 struct _STLP_CLASS_DECLSPEC _STLP_mutex_base
       
   314 {
       
   315 #if defined(_STLP_ATOMIC_EXCHANGE) || defined(_STLP_SGI_THREADS)
       
   316   // It should be relatively easy to get this to work on any modern Unix.
       
   317   volatile __stl_atomic_t _M_lock;
       
   318 #endif
       
   319 
       
   320 #ifdef _STLP_THREADS
       
   321 
       
   322 # ifdef _STLP_ATOMIC_EXCHANGE
       
   323   inline void _M_initialize() { _M_lock=0; }
       
   324   inline void _M_destroy() {}
       
   325 
       
   326   void _M_acquire_lock() {
       
   327     _STLP_mutex_spin<0>::_M_do_lock(&_M_lock);
       
   328   }
       
   329 
       
   330   inline void _M_release_lock() {
       
   331     volatile __stl_atomic_t* __lock = &_M_lock;
       
   332 #  if defined(_STLP_SGI_THREADS) && defined(__GNUC__) && __mips >= 3
       
   333         asm("sync");
       
   334         *__lock = 0;
       
   335 #  elif defined(_STLP_SGI_THREADS) && __mips >= 3 \
       
   336 	 && (defined (_ABIN32) || defined(_ABI64))
       
   337         __lock_release(__lock);
       
   338 #  elif defined (_STLP_SPARC_SOLARIS_THREADS)
       
   339 #   if defined (__WORD64) || defined (__arch64__) || defined (__sparcv9) || defined (__sparcv8plus)
       
   340 	asm("membar #StoreStore ; membar #LoadStore");
       
   341 #   else
       
   342 	asm(" stbar ");
       
   343 #   endif
       
   344         *__lock = 0;	
       
   345 #  else
       
   346         *__lock = 0;
       
   347         // This is not sufficient on many multiprocessors, since
       
   348         // writes to protected variables and the lock may be reordered.
       
   349 #  endif
       
   350   }
       
   351 # elif defined(_STLP_PTHREADS)
       
   352 #  ifdef _STLP_USE_PTHREAD_SPINLOCK
       
   353   pthread_spinlock_t _M_lock;
       
   354   inline void _M_initialize() { pthread_spin_init( &_M_lock, 0 ); }
       
   355   inline void _M_destroy() { pthread_spin_destroy( &_M_lock ); }
       
   356 
       
   357   inline void _M_acquire_lock() { 
       
   358     // we do not care about race conditions here : there is only one thread at this point 
       
   359     if(!_M_lock) pthread_spin_init( &_M_lock, 0 );
       
   360 
       
   361     // fbp: here, initialization on demand should happen before the lock
       
   362     // we use simple strategy as we are sure this only happens on initialization
       
   363     pthread_spin_lock( &_M_lock );
       
   364   }
       
   365 
       
   366   inline void _M_acquire_lock_nodemand() { 
       
   367     pthread_spin_lock( &_M_lock ); 
       
   368   }
       
   369   inline void _M_release_lock() { pthread_spin_unlock( &_M_lock ); }
       
   370 #  else // !_STLP_USE_PTHREAD_SPINLOCK
       
   371   pthread_mutex_t _M_lock;
       
   372 
       
   373   inline void _M_initialize() {
       
   374     pthread_mutex_init(&_M_lock,_STLP_PTHREAD_ATTR_DEFAULT);
       
   375   }
       
   376   inline void _M_destroy() {
       
   377     pthread_mutex_destroy(&_M_lock);
       
   378   }
       
   379   inline void _M_acquire_lock_nodemand() { 
       
   380     pthread_mutex_lock(&_M_lock);
       
   381   }
       
   382 
       
   383   inline void _M_acquire_lock() { 
       
   384 #    if defined (__hpux) && !defined (PTHREAD_MUTEX_INITIALIZER)
       
   385       if (!_M_lock.field1)  _M_initialize();
       
   386 #    endif
       
   387      pthread_mutex_lock(&_M_lock);
       
   388   }
       
   389   inline void _M_release_lock() { pthread_mutex_unlock(&_M_lock); }
       
   390 #  endif // !_STLP_USE_PTHREAD_SPINLOCK
       
   391   
       
   392 # elif defined (_STLP_UITHREADS)
       
   393   mutex_t _M_lock;
       
   394   inline void _M_initialize() {
       
   395     mutex_init(&_M_lock,0,NULL);	
       
   396   }
       
   397   inline void _M_destroy() {
       
   398     mutex_destroy(&_M_lock);
       
   399   }
       
   400   inline void _M_acquire_lock() { mutex_lock(&_M_lock); }
       
   401   inline void _M_release_lock() { mutex_unlock(&_M_lock); }
       
   402 
       
   403 # elif defined(_STLP_OS2THREADS)
       
   404   HMTX _M_lock;
       
   405   inline void _M_initialize() { DosCreateMutexSem(NULL, &_M_lock, 0, false); }
       
   406   inline void _M_destroy() { DosCloseMutexSem(_M_lock); }
       
   407   inline void _M_acquire_lock_nodemand() {
       
   408     DosRequestMutexSem(_M_lock, SEM_INDEFINITE_WAIT);
       
   409   }  
       
   410   inline void _M_acquire_lock() {
       
   411     if(!_M_lock) _M_initialize();
       
   412     DosRequestMutexSem(_M_lock, SEM_INDEFINITE_WAIT);
       
   413   }
       
   414   inline void _M_release_lock() { DosReleaseMutexSem(_M_lock); }
       
   415 # elif defined(_STLP_BETHREADS)
       
   416   sem_id sem;
       
   417   inline void _M_initialize() 
       
   418   {
       
   419      sem = create_sem(1, "STLPort");
       
   420      assert(sem > 0);
       
   421   }
       
   422   inline void _M_destroy() 
       
   423   {
       
   424      int t = delete_sem(sem);
       
   425      assert(t == B_NO_ERROR);
       
   426   }
       
   427   inline void _M_acquire_lock_nodemand()
       
   428   {
       
   429     status_t t;
       
   430     t = acquire_sem(sem);
       
   431     assert(t == B_NO_ERROR);
       
   432   }
       
   433   inline void _M_acquire_lock();
       
   434   inline void _M_release_lock() 
       
   435   {
       
   436      status_t t = release_sem(sem);
       
   437      assert(t == B_NO_ERROR);
       
   438   }
       
   439 # elif defined(_STLP_VXWORKS_THREADS)
       
   440   SEM_ID _M_sem;
       
   441   inline void _M_initialize() 
       
   442   {
       
   443      _M_sem = semMCreate(SEM_Q_FIFO);
       
   444      assert(_M_sem > 0);
       
   445   }
       
   446   inline void _M_destroy() 
       
   447   {
       
   448     STATUS __s;
       
   449     semDelete (_M_sem);
       
   450     assert(__s == OK);
       
   451   }
       
   452   inline void _M_acquire_lock_nodemand()
       
   453   {
       
   454     STATUS __s;
       
   455     semTake (_M_sem, WAIT_FOREVER);
       
   456     assert(__s == OK);
       
   457   }
       
   458   inline void _M_acquire_lock()
       
   459   {
       
   460     if (!_M_sem)
       
   461       _M_initialize();
       
   462     _M_acquire_lock_nodemand();
       
   463   }
       
   464   inline void _M_release_lock() 
       
   465   {
       
   466     STATUS __s;
       
   467     semGive (_M_sem, WAIT_FOREVER);
       
   468     assert(__s == OK);
       
   469   }
       
   470 # else		//*ty 11/24/2001 - added configuration check
       
   471 #  error "Unknown thread facility configuration"
       
   472 # endif
       
   473 #else /* No threads */
       
   474   inline void _M_initialize() {}
       
   475   inline void _M_destroy() {}
       
   476   inline void _M_acquire_lock() {}
       
   477   inline void _M_release_lock() {}
       
   478 #endif // _STLP_PTHREADS
       
   479 };
       
   480 
       
   481 
       
   482 #if defined (_STLP_THREADS) && defined (_STLP_MUTEX_NEEDS_ONDEMAND_INITIALIZATION)
       
   483 // for use in _STLP_mutex, our purposes do not require ondemand initialization
       
   484 // also, mutex_base may use some hacks to determine uninitialized state by zero data, which only works for globals.
       
   485 class _STLP_CLASS_DECLSPEC _STLP_mutex_nodemand : public _STLP_mutex_base {
       
   486   inline void _M_acquire_lock() { 
       
   487     _M_acquire_lock_nodemand();
       
   488   }
       
   489 };
       
   490 #else
       
   491 typedef _STLP_mutex_base _STLP_mutex_nodemand;
       
   492 #endif
       
   493 
       
   494 
       
   495 // Locking class.  The constructor initializes the lock, the destructor destroys it.
       
   496 // Well - behaving class, does not need static initializer
       
   497 class _STLP_CLASS_DECLSPEC _STLP_mutex : public _STLP_mutex_nodemand {
       
   498   public:
       
   499     inline _STLP_mutex () { _M_initialize(); }
       
   500     inline ~_STLP_mutex () { _M_destroy(); }
       
   501   private:
       
   502     _STLP_mutex(const _STLP_mutex&);
       
   503     void operator=(const _STLP_mutex&);
       
   504 };
       
   505 
       
   506 
       
   507 
       
   508 /*
       
   509  * Class _Refcount_Base provides a type, __stl_atomic_t, a data member,
       
   510  * _M_ref_count, and member functions _M_incr and _M_decr, which perform
       
   511  * atomic preincrement/predecrement.  The constructor initializes 
       
   512  * _M_ref_count.
       
   513  */
       
   514 struct _STLP_CLASS_DECLSPEC _Refcount_Base
       
   515 {
       
   516   // The data member _M_ref_count
       
   517   volatile __stl_atomic_t _M_ref_count;
       
   518 
       
   519 # if !defined (_STLP_ATOMIC_EXCHANGE)
       
   520   _STLP_mutex _M_mutex;
       
   521 # endif
       
   522 
       
   523   // Constructor
       
   524   _Refcount_Base(__stl_atomic_t __n) : _M_ref_count(__n) {}
       
   525 
       
   526   // _M_incr and _M_decr
       
   527 # if defined (_STLP_THREADS) && defined (_STLP_ATOMIC_EXCHANGE)
       
   528    void _M_incr() { _STLP_ATOMIC_INCREMENT((__stl_atomic_t*)&_M_ref_count); }
       
   529    void _M_decr() { _STLP_ATOMIC_DECREMENT((__stl_atomic_t*)&_M_ref_count); }
       
   530 # elif defined(_STLP_THREADS)
       
   531   void _M_incr() {
       
   532     _M_mutex._M_acquire_lock();
       
   533     ++_M_ref_count;
       
   534     _M_mutex._M_release_lock();
       
   535   }
       
   536   void _M_decr() {
       
   537     _M_mutex._M_acquire_lock();
       
   538     --_M_ref_count;
       
   539     _M_mutex._M_release_lock();
       
   540   }
       
   541 # else  /* No threads */
       
   542   void _M_incr() { ++_M_ref_count; }
       
   543   void _M_decr() { --_M_ref_count; }
       
   544 # endif
       
   545 };
       
   546 
       
   547 // Atomic swap on unsigned long
       
   548 // This is guaranteed to behave as though it were atomic only if all
       
   549 // possibly concurrent updates use _Atomic_swap.
       
   550 // In some cases the operation is emulated with a lock.
       
   551 # if defined (_STLP_THREADS)
       
   552 #  ifdef _STLP_ATOMIC_EXCHANGE
       
   553 inline __stl_atomic_t _Atomic_swap(volatile __stl_atomic_t * __p, __stl_atomic_t __q) {
       
   554   return (__stl_atomic_t) _STLP_ATOMIC_EXCHANGE(__p,__q);
       
   555 }
       
   556 #  elif defined(_STLP_PTHREADS) || defined (_STLP_UITHREADS) || defined (_STLP_OS2THREADS) || defined(_STLP_USE_PTHREAD_SPINLOCK)
       
   557 // We use a template here only to get a unique initialized instance.
       
   558 template<int __dummy>
       
   559 struct _Swap_lock_struct {
       
   560   static _STLP_STATIC_MUTEX _S_swap_lock;
       
   561 };
       
   562 
       
   563 
       
   564 // This should be portable, but performance is expected
       
   565 // to be quite awful.  This really needs platform specific
       
   566 // code.
       
   567 inline __stl_atomic_t _Atomic_swap(volatile __stl_atomic_t * __p, __stl_atomic_t __q) {
       
   568   _Swap_lock_struct<0>::_S_swap_lock._M_acquire_lock();
       
   569   __stl_atomic_t __result = *__p;
       
   570   *__p = __q;
       
   571   _Swap_lock_struct<0>::_S_swap_lock._M_release_lock();
       
   572   return __result;
       
   573 }
       
   574 #  endif // _STLP_PTHREADS || _STLP_UITHREADS || _STLP_OS2THREADS || _STLP_USE_PTHREAD_SPINLOCK
       
   575 # else // !_STLP_THREADS
       
   576 /* no threads */
       
   577 static inline __stl_atomic_t  _STLP_CALL
       
   578 _Atomic_swap(volatile __stl_atomic_t * __p, __stl_atomic_t __q) {
       
   579   __stl_atomic_t __result = *__p;
       
   580   *__p = __q;
       
   581   return __result;
       
   582 }
       
   583 # endif // _STLP_THREADS
       
   584 
       
   585 // A locking class that uses _STLP_STATIC_MUTEX.  The constructor takes
       
   586 // a reference to an _STLP_STATIC_MUTEX, and acquires a lock.  The destructor
       
   587 // releases the lock.
       
   588 
       
   589 struct _STLP_CLASS_DECLSPEC _STLP_auto_lock
       
   590 {
       
   591   _STLP_STATIC_MUTEX& _M_lock;
       
   592   
       
   593   _STLP_auto_lock(_STLP_STATIC_MUTEX& __lock) : _M_lock(__lock)
       
   594     { _M_lock._M_acquire_lock(); }
       
   595   ~_STLP_auto_lock() { _M_lock._M_release_lock(); }
       
   596 
       
   597 private:
       
   598   void operator=(const _STLP_auto_lock&);
       
   599   _STLP_auto_lock(const _STLP_auto_lock&);
       
   600 };
       
   601 
       
   602 typedef _STLP_auto_lock _STLP_mutex_lock;
       
   603 
       
   604 #ifdef _STLP_BETHREADS
       
   605 
       
   606 template <int __inst>
       
   607 struct _STLP_beos_static_lock_data
       
   608 {
       
   609 	static bool is_init;
       
   610 	struct mutex_t : public _STLP_mutex
       
   611 	{
       
   612 		mutex_t()
       
   613 		{
       
   614 			_STLP_beos_static_lock_data<0>::is_init = true;
       
   615 		}
       
   616 		~mutex_t()
       
   617 		{
       
   618 			_STLP_beos_static_lock_data<0>::is_init = false;
       
   619 		}
       
   620 	};
       
   621 	static mutex_t mut;
       
   622 };
       
   623 
       
   624 template <int __inst>
       
   625 bool _STLP_beos_static_lock_data<__inst>::is_init = false;
       
   626 template <int __inst>
       
   627 typename _STLP_beos_static_lock_data<__inst>::mutex_t _STLP_beos_static_lock_data<__inst>::mut;
       
   628 
       
   629 
       
   630 inline void _STLP_mutex_base::_M_acquire_lock() 
       
   631 {
       
   632 	if(sem == 0)
       
   633 	{
       
   634 		// we need to initialise on demand here
       
   635 		// to prevent race conditions use our global
       
   636 		// mutex if it's available:
       
   637 		if(_STLP_beos_static_lock_data<0>::is_init)
       
   638 		{
       
   639 			_STLP_auto_lock al(_STLP_beos_static_lock_data<0>::mut);
       
   640 			if(sem == 0) _M_initialize();
       
   641 		}
       
   642 		else
       
   643 		{
       
   644 			// no lock available, we must still be
       
   645 			// in startup code, THERE MUST BE ONE THREAD
       
   646 			// ONLY active at this point.
       
   647 			_M_initialize();
       
   648 		}
       
   649 	}
       
   650 	_M_acquire_lock_nodemand();
       
   651 }
       
   652 
       
   653 #endif
       
   654 
       
   655 _STLP_END_NAMESPACE
       
   656 
       
   657 # if !defined (_STLP_LINK_TIME_INSTANTIATION)
       
   658 #  include <stl/_threads.c>
       
   659 # endif
       
   660 
       
   661 #endif /* _STLP_INTERNAL_THREADS_H */
       
   662 
       
   663 // Local Variables:
       
   664 // mode:C++
       
   665 // End:
       
   666