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