epoc32/include/tools/stlport/stl/_threads.h
author William Roberts <williamr@symbian.org>
Wed, 31 Mar 2010 12:33:34 +0100
branchSymbian3
changeset 4 837f303aceeb
permissions -rw-r--r--
Current Symbian^3 public API header files (from PDK 3.0.h)
This is the epoc32/include tree with the "platform" subtrees removed, and
all but a selected few mbg and rsg files removed.
williamr@4
     1
/*
williamr@4
     2
 * Copyright (c) 1997-1999
williamr@4
     3
 * Silicon Graphics Computer Systems, Inc.
williamr@4
     4
 *
williamr@4
     5
 * Copyright (c) 1999
williamr@4
     6
 * Boris Fomitchev
williamr@4
     7
 *
williamr@4
     8
 * This material is provided "as is", with absolutely no warranty expressed
williamr@4
     9
 * or implied. Any use is at your own risk.
williamr@4
    10
 *
williamr@4
    11
 * Permission to use or copy this software for any purpose is hereby granted
williamr@4
    12
 * without fee, provided the above notices are retained on all copies.
williamr@4
    13
 * Permission to modify the code and to distribute modified code is granted,
williamr@4
    14
 * provided the above notices are retained, and a notice that the code was
williamr@4
    15
 * modified is included with the above copyright notice.
williamr@4
    16
 *
williamr@4
    17
 */
williamr@4
    18
williamr@4
    19
// WARNING: This is an internal header file, included by other C++
williamr@4
    20
// standard library headers.  You should not attempt to use this header
williamr@4
    21
// file directly.
williamr@4
    22
williamr@4
    23
williamr@4
    24
#ifndef _STLP_INTERNAL_THREADS_H
williamr@4
    25
#define _STLP_INTERNAL_THREADS_H
williamr@4
    26
williamr@4
    27
// Supported threading models are native SGI, pthreads, uithreads
williamr@4
    28
// (similar to pthreads, but based on an earlier draft of the Posix
williamr@4
    29
// threads standard), and Win32 threads.  Uithread support by Jochen
williamr@4
    30
// Schlick, 1999, and Solaris threads generalized to them.
williamr@4
    31
williamr@4
    32
#ifndef _STLP_INTERNAL_CSTDDEF
williamr@4
    33
#  include <stl/_cstddef.h>
williamr@4
    34
#endif
williamr@4
    35
williamr@4
    36
#ifndef _STLP_INTERNAL_CSTDLIB
williamr@4
    37
#  include <stl/_cstdlib.h>
williamr@4
    38
#endif
williamr@4
    39
williamr@4
    40
// On SUN and Mac OS X gcc, zero-initialization works just fine...
williamr@4
    41
#if defined (__sun) || (defined (__GNUC__) && defined(__APPLE__))
williamr@4
    42
#  define _STLP_MUTEX_INITIALIZER
williamr@4
    43
#endif
williamr@4
    44
williamr@4
    45
/* This header defines the following atomic operation that platform should
williamr@4
    46
 * try to support as much as possible. Atomic operation are exposed as macro
williamr@4
    47
 * in order to easily test for their existance. They are:
williamr@4
    48
 * __stl_atomic_t _STLP_ATOMIC_INCREMENT(volatile __stl_atomic_t* __ptr) :
williamr@4
    49
 * increment *__ptr by 1 and returns the new value
williamr@4
    50
 * __stl_atomic_t _STLP_ATOMIC_DECREMENT(volatile __stl_atomic_t* __ptr) :
williamr@4
    51
 * decrement  *__ptr by 1 and returns the new value
williamr@4
    52
 * __stl_atomic_t _STLP_ATOMIC_EXCHANGE(volatile __stl_atomic_t* __target, __stl_atomic_t __val) :
williamr@4
    53
 * assign __val to *__target and returns former *__target value
williamr@4
    54
 * void* _STLP_ATOMIC_EXCHANGE_PTR(void* volatile* __target, void* __ptr) :
williamr@4
    55
 * assign __ptr to *__target and returns former *__target value
williamr@4
    56
 * __stl_atomic_t _STLP_ATOMIC_ADD(volatile __stl_atomic_t* __target, __stl_atomic_t __val) :
williamr@4
    57
 * does *__target = *__target + __val and returns the old *__target value
williamr@4
    58
 */
williamr@4
    59
williamr@4
    60
#if defined (_STLP_WIN32) || defined (__sgi) || defined (_STLP_SPARC_SOLARIS_THREADS)
williamr@4
    61
typedef long __stl_atomic_t;
williamr@4
    62
#else
williamr@4
    63
/* Don't import whole namespace!!!! - ptr */
williamr@4
    64
// # if defined (_STLP_USE_NAMESPACES) && ! defined (_STLP_VENDOR_GLOBAL_CSTD)
williamr@4
    65
// // using _STLP_VENDOR_CSTD::size_t;
williamr@4
    66
// using namespace _STLP_VENDOR_CSTD;
williamr@4
    67
// # endif
williamr@4
    68
typedef size_t __stl_atomic_t;
williamr@4
    69
#endif
williamr@4
    70
williamr@4
    71
#if defined (_STLP_THREADS)
williamr@4
    72
williamr@4
    73
#  if defined (_STLP_SGI_THREADS)
williamr@4
    74
williamr@4
    75
#    include <mutex.h>
williamr@4
    76
// Hack for SGI o32 compilers.
williamr@4
    77
#    if !defined(__add_and_fetch) && \
williamr@4
    78
        (__mips < 3 || !(defined (_ABIN32) || defined(_ABI64)))
williamr@4
    79
#      define __add_and_fetch(__l,__v) add_then_test((unsigned long*)__l,__v)
williamr@4
    80
#      define __test_and_set(__l,__v)  test_and_set(__l,__v)
williamr@4
    81
#    endif /* o32 */
williamr@4
    82
williamr@4
    83
#    if __mips < 3 || !(defined (_ABIN32) || defined(_ABI64))
williamr@4
    84
#      define _STLP_ATOMIC_EXCHANGE(__p, __q) test_and_set(__p, __q)
williamr@4
    85
#    else
williamr@4
    86
#      define _STLP_ATOMIC_EXCHANGE(__p, __q) __test_and_set((unsigned long*)__p, (unsigned long)__q)
williamr@4
    87
#    endif
williamr@4
    88
williamr@4
    89
#    define _STLP_ATOMIC_INCREMENT(__x) __add_and_fetch(__x, 1)
williamr@4
    90
#    define _STLP_ATOMIC_DECREMENT(__x) __add_and_fetch(__x, (size_t) -1)
williamr@4
    91
williamr@4
    92
#  elif defined (_STLP_PTHREADS)
williamr@4
    93
williamr@4
    94
#    include <pthread.h>
williamr@4
    95
#    if !defined (_STLP_USE_PTHREAD_SPINLOCK)
williamr@4
    96
#      if defined (PTHREAD_MUTEX_INITIALIZER) && !defined (_STLP_MUTEX_INITIALIZER) && defined (_REENTRANT)
williamr@4
    97
#        define _STLP_MUTEX_INITIALIZER = { PTHREAD_MUTEX_INITIALIZER }
williamr@4
    98
#      endif
williamr@4
    99
//HPUX variants have (on some platforms optional) non-standard "DCE" pthreads impl
williamr@4
   100
#      if defined (_DECTHREADS_) && (defined (_PTHREAD_USE_D4) || defined (__hpux)) && !defined (_CMA_SUPPRESS_EXTERNALS_)
williamr@4
   101
#        define _STLP_PTHREAD_ATTR_DEFAULT pthread_mutexattr_default
williamr@4
   102
#      else
williamr@4
   103
#        define _STLP_PTHREAD_ATTR_DEFAULT 0
williamr@4
   104
#      endif
williamr@4
   105
#    else // _STLP_USE_PTHREAD_SPINLOCK
williamr@4
   106
#      if defined (__OpenBSD__)
williamr@4
   107
#        include <spinlock.h>
williamr@4
   108
#      endif
williamr@4
   109
#    endif // _STLP_USE_PTHREAD_SPINLOCK
williamr@4
   110
williamr@4
   111
#    if defined (__GNUC__) && defined (__i386__)
williamr@4
   112
williamr@4
   113
#      if !defined (_STLP_ATOMIC_INCREMENT)
williamr@4
   114
inline long _STLP_atomic_increment_gcc_x86(long volatile* p) {
williamr@4
   115
  long result;
williamr@4
   116
  __asm__ __volatile__
williamr@4
   117
    ("lock; xaddl  %1, %0;"
williamr@4
   118
    :"=m" (*p), "=r" (result)
williamr@4
   119
    :"m" (*p),  "1"  (1)
williamr@4
   120
    :"cc");
williamr@4
   121
  return result + 1;
williamr@4
   122
}
williamr@4
   123
#        define _STLP_ATOMIC_INCREMENT(__x) (_STLP_atomic_increment_gcc_x86((long volatile*)__x))
williamr@4
   124
#      endif
williamr@4
   125
williamr@4
   126
#      if !defined (_STLP_ATOMIC_DECREMENT)
williamr@4
   127
inline long _STLP_atomic_decrement_gcc_x86(long volatile* p) {
williamr@4
   128
  long result;
williamr@4
   129
  __asm__ __volatile__
williamr@4
   130
    ("lock; xaddl  %1, %0;"
williamr@4
   131
    :"=m" (*p), "=r" (result)
williamr@4
   132
    :"m" (*p),  "1"  (-1)
williamr@4
   133
    :"cc");
williamr@4
   134
  return result - 1;
williamr@4
   135
}
williamr@4
   136
#        define _STLP_ATOMIC_DECREMENT(__x) (_STLP_atomic_decrement_gcc_x86((long volatile*)__x))
williamr@4
   137
#      endif
williamr@4
   138
williamr@4
   139
#      if !defined (_STLP_ATOMIC_ADD)
williamr@4
   140
inline long _STLP_atomic_add_gcc_x86(long volatile* p, long addend) {
williamr@4
   141
  long result;
williamr@4
   142
  __asm__ __volatile__
williamr@4
   143
    ("lock; xaddl %1, %0;"
williamr@4
   144
    :"=m" (*p), "=r" (result)
williamr@4
   145
    :"m"  (*p), "1"  (addend)
williamr@4
   146
    :"cc");
williamr@4
   147
 return result + addend;
williamr@4
   148
}
williamr@4
   149
#        define _STLP_ATOMIC_ADD(__dst, __val)  (_STLP_atomic_add_gcc_x86((long volatile*)__dst, (long)__val))
williamr@4
   150
#      endif
williamr@4
   151
williamr@4
   152
#    endif /* if defined(__GNUC__) && defined(__i386__) */
williamr@4
   153
williamr@4
   154
#  elif defined (_STLP_WIN32THREADS)
williamr@4
   155
williamr@4
   156
#    if !defined (_STLP_ATOMIC_INCREMENT)
williamr@4
   157
#      if !defined (_STLP_NEW_PLATFORM_SDK)
williamr@4
   158
#        define _STLP_ATOMIC_INCREMENT(__x)           InterlockedIncrement(__CONST_CAST(long*, __x))
williamr@4
   159
#        define _STLP_ATOMIC_DECREMENT(__x)           InterlockedDecrement(__CONST_CAST(long*, __x))
williamr@4
   160
#        define _STLP_ATOMIC_EXCHANGE(__x, __y)       InterlockedExchange(__CONST_CAST(long*, __x), __y)
williamr@4
   161
#      else
williamr@4
   162
#        define _STLP_ATOMIC_INCREMENT(__x)           InterlockedIncrement(__x)
williamr@4
   163
#        define _STLP_ATOMIC_DECREMENT(__x)           InterlockedDecrement(__x)
williamr@4
   164
#        define _STLP_ATOMIC_EXCHANGE(__x, __y)       InterlockedExchange(__x, __y)
williamr@4
   165
#      endif
williamr@4
   166
#      define _STLP_ATOMIC_EXCHANGE_PTR(__x, __y)     STLPInterlockedExchangePointer(__x, __y)
williamr@4
   167
/*
williamr@4
   168
 * The following functionnality is only available since Windows 98, those that are targeting previous OSes
williamr@4
   169
 * should define _WIN32_WINDOWS to a value lower that the one of Win 98, see Platform SDK documentation for
williamr@4
   170
 * more informations:
williamr@4
   171
 */
williamr@4
   172
#      if defined (_STLP_NEW_PLATFORM_SDK) && (!defined (WINVER) || (WINVER >= 0x0410)) && \
williamr@4
   173
                                              (!defined (_WIN32_WINDOWS) || (_WIN32_WINDOWS >= 0x0410))
williamr@4
   174
#        define _STLP_ATOMIC_ADD(__dst, __val) InterlockedExchangeAdd(__dst, __val)
williamr@4
   175
#      endif
williamr@4
   176
#    endif
williamr@4
   177
williamr@4
   178
#  elif defined (__DECC) || defined (__DECCXX)
williamr@4
   179
williamr@4
   180
#    include <machine/builtins.h>
williamr@4
   181
#    define _STLP_ATOMIC_EXCHANGE __ATOMIC_EXCH_LONG
williamr@4
   182
#    define _STLP_ATOMIC_INCREMENT(__x) __ATOMIC_ADD_LONG(__x, 1)
williamr@4
   183
#    define _STLP_ATOMIC_DECREMENT(__x) __ATOMIC_ADD_LONG(__x, -1)
williamr@4
   184
williamr@4
   185
#  elif defined(_STLP_SPARC_SOLARIS_THREADS)
williamr@4
   186
williamr@4
   187
#    include <stl/_sparc_atomic.h>
williamr@4
   188
williamr@4
   189
#  elif defined (_STLP_UITHREADS)
williamr@4
   190
williamr@4
   191
// this inclusion is potential hazard to bring up all sorts
williamr@4
   192
// of old-style headers. Let's assume vendor already know how
williamr@4
   193
// to deal with that.
williamr@4
   194
#    ifndef _STLP_INTERNAL_CTIME
williamr@4
   195
#      include <stl/_ctime.h>
williamr@4
   196
#    endif
williamr@4
   197
#    if defined (_STLP_USE_NAMESPACES) && ! defined (_STLP_VENDOR_GLOBAL_CSTD)
williamr@4
   198
using _STLP_VENDOR_CSTD::time_t;
williamr@4
   199
#    endif
williamr@4
   200
#    include <synch.h>
williamr@4
   201
#    include <cstdio>
williamr@4
   202
#    include <cwchar>
williamr@4
   203
williamr@4
   204
#  elif defined (_STLP_BETHREADS)
williamr@4
   205
williamr@4
   206
#    include <OS.h>
williamr@4
   207
#    include <cassert>
williamr@4
   208
#    include <stdio.h>
williamr@4
   209
#    define _STLP_MUTEX_INITIALIZER = { 0 }
williamr@4
   210
williamr@4
   211
#  elif defined (_STLP_NWTHREADS)
williamr@4
   212
williamr@4
   213
#    include <nwthread.h>
williamr@4
   214
#    include <nwsemaph.h>
williamr@4
   215
williamr@4
   216
#  elif defined(_STLP_OS2THREADS)
williamr@4
   217
williamr@4
   218
#    if defined (__GNUC__)
williamr@4
   219
#      define INCL_DOSSEMAPHORES
williamr@4
   220
#      include <os2.h>
williamr@4
   221
#    else
williamr@4
   222
// This section serves to replace os2.h for VisualAge C++
williamr@4
   223
  typedef unsigned long ULONG;
williamr@4
   224
#      if !defined (__HEV__)  /* INCL_SEMAPHORE may also define HEV */
williamr@4
   225
#        define __HEV__
williamr@4
   226
  typedef ULONG HEV;
williamr@4
   227
  typedef HEV*  PHEV;
williamr@4
   228
#      endif
williamr@4
   229
  typedef ULONG APIRET;
williamr@4
   230
  typedef ULONG HMTX;
williamr@4
   231
  typedef HMTX*  PHMTX;
williamr@4
   232
  typedef const char*  PCSZ;
williamr@4
   233
  typedef ULONG BOOL32;
williamr@4
   234
  APIRET _System DosCreateMutexSem(PCSZ pszName, PHEV phev, ULONG flAttr, BOOL32 fState);
williamr@4
   235
  APIRET _System DosRequestMutexSem(HMTX hmtx, ULONG ulTimeout);
williamr@4
   236
  APIRET _System DosReleaseMutexSem(HMTX hmtx);
williamr@4
   237
  APIRET _System DosCloseMutexSem(HMTX hmtx);
williamr@4
   238
#      define _STLP_MUTEX_INITIALIZER = { 0 }
williamr@4
   239
#    endif /* GNUC */
williamr@4
   240
williamr@4
   241
#  endif
williamr@4
   242
williamr@4
   243
#else
williamr@4
   244
/* no threads */
williamr@4
   245
#  define _STLP_ATOMIC_INCREMENT(__x) ++(*__x)
williamr@4
   246
#  define _STLP_ATOMIC_DECREMENT(__x) --(*__x)
williamr@4
   247
/* We do not grant other atomic operations as they are useless if STLport do not have
williamr@4
   248
 * to be thread safe
williamr@4
   249
 */
williamr@4
   250
#endif
williamr@4
   251
williamr@4
   252
#if !defined (_STLP_MUTEX_INITIALIZER)
williamr@4
   253
#  if defined(_STLP_ATOMIC_EXCHANGE)
williamr@4
   254
#    define _STLP_MUTEX_INITIALIZER = { 0 }
williamr@4
   255
#  elif defined(_STLP_UITHREADS)
williamr@4
   256
#    define _STLP_MUTEX_INITIALIZER = { DEFAULTMUTEX }
williamr@4
   257
#  else
williamr@4
   258
#    define _STLP_MUTEX_INITIALIZER
williamr@4
   259
#  endif
williamr@4
   260
#endif
williamr@4
   261
williamr@4
   262
_STLP_BEGIN_NAMESPACE
williamr@4
   263
williamr@4
   264
#if defined (_STLP_THREADS) && !defined (_STLP_USE_PTHREAD_SPINLOCK)
williamr@4
   265
// Helper struct.  This is a workaround for various compilers that don't
williamr@4
   266
// handle static variables in inline functions properly.
williamr@4
   267
template <int __inst>
williamr@4
   268
struct _STLP_mutex_spin {
williamr@4
   269
  enum { __low_max = 30, __high_max = 1000 };
williamr@4
   270
  // Low if we suspect uniprocessor, high for multiprocessor.
williamr@4
   271
  static unsigned __max;
williamr@4
   272
  static unsigned __last;
williamr@4
   273
  static void _STLP_CALL _M_do_lock(volatile __stl_atomic_t* __lock);
williamr@4
   274
  static void _STLP_CALL _S_nsec_sleep(int __log_nsec);
williamr@4
   275
};
williamr@4
   276
#endif // !_STLP_USE_PTHREAD_SPINLOCK
williamr@4
   277
williamr@4
   278
// Locking class.  Note that this class *does not have a constructor*.
williamr@4
   279
// It must be initialized either statically, with _STLP_MUTEX_INITIALIZER,
williamr@4
   280
// or dynamically, by explicitly calling the _M_initialize member function.
williamr@4
   281
// (This is similar to the ways that a pthreads mutex can be initialized.)
williamr@4
   282
// There are explicit member functions for acquiring and releasing the lock.
williamr@4
   283
williamr@4
   284
// There is no constructor because static initialization is essential for
williamr@4
   285
// some uses, and only a class aggregate (see section 8.5.1 of the C++
williamr@4
   286
// standard) can be initialized that way.  That means we must have no
williamr@4
   287
// constructors, no base classes, no virtual functions, and no private or
williamr@4
   288
// protected members.
williamr@4
   289
williamr@4
   290
// For non-static cases, clients should use  _STLP_mutex.
williamr@4
   291
williamr@4
   292
struct _STLP_CLASS_DECLSPEC _STLP_mutex_base {
williamr@4
   293
#if defined (_STLP_ATOMIC_EXCHANGE) || defined (_STLP_SGI_THREADS)
williamr@4
   294
  // It should be relatively easy to get this to work on any modern Unix.
williamr@4
   295
  volatile __stl_atomic_t _M_lock;
williamr@4
   296
#endif
williamr@4
   297
williamr@4
   298
#if defined (_STLP_THREADS)
williamr@4
   299
#  if defined (_STLP_ATOMIC_EXCHANGE)
williamr@4
   300
  inline void _M_initialize() { _M_lock = 0; }
williamr@4
   301
  inline void _M_destroy() {}
williamr@4
   302
williamr@4
   303
  void _M_acquire_lock() {
williamr@4
   304
    _STLP_mutex_spin<0>::_M_do_lock(&_M_lock);
williamr@4
   305
  }
williamr@4
   306
williamr@4
   307
  inline void _M_release_lock() {
williamr@4
   308
    volatile __stl_atomic_t* __lock = &_M_lock;
williamr@4
   309
#    if defined(_STLP_SGI_THREADS) && defined(__GNUC__) && __mips >= 3
williamr@4
   310
    asm("sync");
williamr@4
   311
    *__lock = 0;
williamr@4
   312
#    elif defined(_STLP_SGI_THREADS) && __mips >= 3 && \
williamr@4
   313
         (defined (_ABIN32) || defined(_ABI64))
williamr@4
   314
    __lock_release(__lock);
williamr@4
   315
#    elif defined (_STLP_SPARC_SOLARIS_THREADS)
williamr@4
   316
#      if defined (__WORD64) || defined (__arch64__) || defined (__sparcv9) || defined (__sparcv8plus)
williamr@4
   317
    asm("membar #StoreStore ; membar #LoadStore");
williamr@4
   318
#      else
williamr@4
   319
    asm(" stbar ");
williamr@4
   320
#      endif
williamr@4
   321
    *__lock = 0;
williamr@4
   322
#    else
williamr@4
   323
    *__lock = 0;
williamr@4
   324
    // This is not sufficient on many multiprocessors, since
williamr@4
   325
    // writes to protected variables and the lock may be reordered.
williamr@4
   326
#    endif
williamr@4
   327
  }
williamr@4
   328
#  elif defined (_STLP_PTHREADS)
williamr@4
   329
#    if defined (_STLP_USE_PTHREAD_SPINLOCK)
williamr@4
   330
#      if !defined (__OpenBSD__)
williamr@4
   331
  pthread_spinlock_t _M_lock;
williamr@4
   332
  inline void _M_initialize() { pthread_spin_init( &_M_lock, 0 ); }
williamr@4
   333
  inline void _M_destroy() { pthread_spin_destroy( &_M_lock ); }
williamr@4
   334
williamr@4
   335
  // sorry, but no static initializer for pthread_spinlock_t;
williamr@4
   336
  // this will not work for compilers that has problems with call
williamr@4
   337
  // constructor of static object...
williamr@4
   338
williamr@4
   339
  // _STLP_mutex_base()
williamr@4
   340
  //   { pthread_spin_init( &_M_lock, 0 ); }
williamr@4
   341
williamr@4
   342
  // ~_STLP_mutex_base()
williamr@4
   343
  //   { pthread_spin_destroy( &_M_lock ); }
williamr@4
   344
williamr@4
   345
  inline void _M_acquire_lock() { pthread_spin_lock( &_M_lock ); }
williamr@4
   346
  inline void _M_release_lock() { pthread_spin_unlock( &_M_lock ); }
williamr@4
   347
#      else // __OpenBSD__
williamr@4
   348
  spinlock_t _M_lock;
williamr@4
   349
  inline void _M_initialize() { _SPINLOCK_INIT( &_M_lock ); }
williamr@4
   350
  inline void _M_destroy() { }
williamr@4
   351
  inline void _M_acquire_lock() { _SPINLOCK( &_M_lock ); }
williamr@4
   352
  inline void _M_release_lock() { _SPINUNLOCK( &_M_lock ); }
williamr@4
   353
#      endif // __OpenBSD__
williamr@4
   354
#    else // !_STLP_USE_PTHREAD_SPINLOCK
williamr@4
   355
  pthread_mutex_t _M_lock;
williamr@4
   356
  inline void _M_initialize()
williamr@4
   357
  { pthread_mutex_init(&_M_lock,_STLP_PTHREAD_ATTR_DEFAULT); }
williamr@4
   358
  inline void _M_destroy()
williamr@4
   359
  { pthread_mutex_destroy(&_M_lock); }
williamr@4
   360
  inline void _M_acquire_lock() {
williamr@4
   361
#      if defined ( __hpux ) && ! defined (PTHREAD_MUTEX_INITIALIZER)
williamr@4
   362
    if (!_M_lock.field1)  _M_initialize();
williamr@4
   363
#      endif
williamr@4
   364
    pthread_mutex_lock(&_M_lock);
williamr@4
   365
  }
williamr@4
   366
  inline void _M_release_lock() { pthread_mutex_unlock(&_M_lock); }
williamr@4
   367
#    endif // !_STLP_USE_PTHREAD_SPINLOCK
williamr@4
   368
williamr@4
   369
#  elif defined (_STLP_UITHREADS)
williamr@4
   370
  mutex_t _M_lock;
williamr@4
   371
  inline void _M_initialize()
williamr@4
   372
  { mutex_init(&_M_lock, 0, NULL); }
williamr@4
   373
  inline void _M_destroy()
williamr@4
   374
  { mutex_destroy(&_M_lock); }
williamr@4
   375
  inline void _M_acquire_lock() { mutex_lock(&_M_lock); }
williamr@4
   376
  inline void _M_release_lock() { mutex_unlock(&_M_lock); }
williamr@4
   377
williamr@4
   378
#  elif defined (_STLP_OS2THREADS)
williamr@4
   379
  HMTX _M_lock;
williamr@4
   380
  inline void _M_initialize() { DosCreateMutexSem(NULL, &_M_lock, 0, false); }
williamr@4
   381
  inline void _M_destroy() { DosCloseMutexSem(_M_lock); }
williamr@4
   382
  inline void _M_acquire_lock() {
williamr@4
   383
    if (!_M_lock) _M_initialize();
williamr@4
   384
    DosRequestMutexSem(_M_lock, SEM_INDEFINITE_WAIT);
williamr@4
   385
  }
williamr@4
   386
  inline void _M_release_lock() { DosReleaseMutexSem(_M_lock); }
williamr@4
   387
#  elif defined (_STLP_BETHREADS)
williamr@4
   388
  sem_id sem;
williamr@4
   389
  inline void _M_initialize() {
williamr@4
   390
    sem = create_sem(1, "STLPort");
williamr@4
   391
    assert(sem > 0);
williamr@4
   392
  }
williamr@4
   393
  inline void _M_destroy() {
williamr@4
   394
    int t = delete_sem(sem);
williamr@4
   395
    assert(t == B_NO_ERROR);
williamr@4
   396
  }
williamr@4
   397
  inline void _M_acquire_lock();
williamr@4
   398
  inline void _M_release_lock() {
williamr@4
   399
    status_t t = release_sem(sem);
williamr@4
   400
    assert(t == B_NO_ERROR);
williamr@4
   401
  }
williamr@4
   402
#  elif defined (_STLP_NWTHREADS)
williamr@4
   403
  LONG _M_lock;
williamr@4
   404
  inline void _M_initialize()
williamr@4
   405
  { _M_lock = OpenLocalSemaphore(1); }
williamr@4
   406
  inline void _M_destroy()
williamr@4
   407
  { CloseLocalSemaphore(_M_lock); }
williamr@4
   408
  inline void _M_acquire_lock()
williamr@4
   409
  { WaitOnLocalSemaphore(_M_lock); }
williamr@4
   410
  inline void _M_release_lock() { SignalLocalSemaphore(_M_lock); }
williamr@4
   411
#  else      //*ty 11/24/2001 - added configuration check
williamr@4
   412
#    error "Unknown thread facility configuration"
williamr@4
   413
#  endif
williamr@4
   414
#else /* No threads */
williamr@4
   415
  inline void _M_initialize() {}
williamr@4
   416
  inline void _M_destroy() {}
williamr@4
   417
  inline void _M_acquire_lock() {}
williamr@4
   418
  inline void _M_release_lock() {}
williamr@4
   419
#endif // _STLP_PTHREADS
williamr@4
   420
};
williamr@4
   421
williamr@4
   422
// Locking class.  The constructor initializes the lock, the destructor destroys it.
williamr@4
   423
// Well - behaving class, does not need static initializer
williamr@4
   424
williamr@4
   425
class _STLP_CLASS_DECLSPEC _STLP_mutex : public _STLP_mutex_base {
williamr@4
   426
  public:
williamr@4
   427
    inline _STLP_mutex () { _M_initialize(); }
williamr@4
   428
    inline ~_STLP_mutex () { _M_destroy(); }
williamr@4
   429
  private:
williamr@4
   430
    _STLP_mutex(const _STLP_mutex&);
williamr@4
   431
    void operator=(const _STLP_mutex&);
williamr@4
   432
};
williamr@4
   433
williamr@4
   434
// A locking class that uses _STLP_STATIC_MUTEX.  The constructor takes
williamr@4
   435
// a reference to an _STLP_STATIC_MUTEX, and acquires a lock.  The destructor
williamr@4
   436
// releases the lock.
williamr@4
   437
// It's not clear that this is exactly the right functionality.
williamr@4
   438
// It will probably change in the future.
williamr@4
   439
williamr@4
   440
struct _STLP_CLASS_DECLSPEC _STLP_auto_lock {
williamr@4
   441
  _STLP_auto_lock(_STLP_STATIC_MUTEX& __lock) : _M_lock(__lock)
williamr@4
   442
  { _M_lock._M_acquire_lock(); }
williamr@4
   443
  ~_STLP_auto_lock()
williamr@4
   444
  { _M_lock._M_release_lock(); }
williamr@4
   445
williamr@4
   446
private:
williamr@4
   447
  _STLP_STATIC_MUTEX& _M_lock;
williamr@4
   448
  void operator=(const _STLP_auto_lock&);
williamr@4
   449
  _STLP_auto_lock(const _STLP_auto_lock&);
williamr@4
   450
};
williamr@4
   451
williamr@4
   452
/*
williamr@4
   453
 * Class _Refcount_Base provides a type, __stl_atomic_t, a data member,
williamr@4
   454
 * _M_ref_count, and member functions _M_incr and _M_decr, which perform
williamr@4
   455
 * atomic preincrement/predecrement.  The constructor initializes
williamr@4
   456
 * _M_ref_count.
williamr@4
   457
 */
williamr@4
   458
class _STLP_CLASS_DECLSPEC _Refcount_Base {
williamr@4
   459
  // The data member _M_ref_count
williamr@4
   460
#if defined (__DMC__)
williamr@4
   461
public:
williamr@4
   462
#endif
williamr@4
   463
  _STLP_VOLATILE __stl_atomic_t _M_ref_count;
williamr@4
   464
williamr@4
   465
#if !defined (_STLP_ATOMIC_EXCHANGE)
williamr@4
   466
  _STLP_mutex _M_mutex;
williamr@4
   467
#endif
williamr@4
   468
williamr@4
   469
  public:
williamr@4
   470
  // Constructor
williamr@4
   471
  _Refcount_Base(__stl_atomic_t __n) : _M_ref_count(__n) {}
williamr@4
   472
williamr@4
   473
  // _M_incr and _M_decr
williamr@4
   474
#if defined (_STLP_THREADS)
williamr@4
   475
#  if defined (_STLP_ATOMIC_EXCHANGE)
williamr@4
   476
   int _M_incr() { return _STLP_ATOMIC_INCREMENT(&_M_ref_count); }
williamr@4
   477
   int _M_decr() { return _STLP_ATOMIC_DECREMENT(&_M_ref_count); }
williamr@4
   478
#  else
williamr@4
   479
  int _M_incr() {
williamr@4
   480
    _STLP_auto_lock l(_M_mutex);
williamr@4
   481
    return ++_M_ref_count;
williamr@4
   482
  }
williamr@4
   483
  int _M_decr() {
williamr@4
   484
    _STLP_auto_lock l(_M_mutex);
williamr@4
   485
    return --_M_ref_count;
williamr@4
   486
  }
williamr@4
   487
#  endif
williamr@4
   488
#else  /* No threads */
williamr@4
   489
  int _M_incr() { return ++_M_ref_count; }
williamr@4
   490
  int _M_decr() { return --_M_ref_count; }
williamr@4
   491
#endif
williamr@4
   492
};
williamr@4
   493
williamr@4
   494
/* Atomic swap on __stl_atomic_t
williamr@4
   495
 * This is guaranteed to behave as though it were atomic only if all
williamr@4
   496
 * possibly concurrent updates use _Atomic_swap.
williamr@4
   497
 * In some cases the operation is emulated with a lock.
williamr@4
   498
 * Idem for _Atomic_swap_ptr
williamr@4
   499
 */
williamr@4
   500
/* Helper struct to handle following cases:
williamr@4
   501
 * - on platforms where sizeof(__stl_atomic_t) == sizeof(void*) atomic
williamr@4
   502
 *   exchange can be done on pointers
williamr@4
   503
 * - on platform without atomic operation swap is done in a critical section,
williamr@4
   504
 *   portable but inefficient.
williamr@4
   505
 */
williamr@4
   506
template <int __use_ptr_atomic_swap>
williamr@4
   507
class _Atomic_swap_struct {
williamr@4
   508
public:
williamr@4
   509
#if defined (_STLP_THREADS) && \
williamr@4
   510
    !defined (_STLP_ATOMIC_EXCHANGE) && \
williamr@4
   511
    (defined (_STLP_PTHREADS) || defined (_STLP_UITHREADS) || defined (_STLP_OS2THREADS) || \
williamr@4
   512
     defined (_STLP_USE_PTHREAD_SPINLOCK) || defined (_STLP_NWTHREADS))
williamr@4
   513
#  define _STLP_USE_ATOMIC_SWAP_MUTEX
williamr@4
   514
  static _STLP_STATIC_MUTEX _S_swap_lock;
williamr@4
   515
#endif
williamr@4
   516
williamr@4
   517
  static __stl_atomic_t _S_swap(_STLP_VOLATILE __stl_atomic_t* __p, __stl_atomic_t __q) {
williamr@4
   518
#if defined (_STLP_THREADS)
williamr@4
   519
#  if defined (_STLP_ATOMIC_EXCHANGE)
williamr@4
   520
  return _STLP_ATOMIC_EXCHANGE(__p, __q);
williamr@4
   521
#  elif defined (_STLP_USE_ATOMIC_SWAP_MUTEX)
williamr@4
   522
  _S_swap_lock._M_acquire_lock();
williamr@4
   523
  __stl_atomic_t __result = *__p;
williamr@4
   524
  *__p = __q;
williamr@4
   525
  _S_swap_lock._M_release_lock();
williamr@4
   526
  return __result;
williamr@4
   527
#  else
williamr@4
   528
#    error Missing atomic swap implementation
williamr@4
   529
#  endif
williamr@4
   530
#else
williamr@4
   531
  /* no threads */
williamr@4
   532
  __stl_atomic_t __result = *__p;
williamr@4
   533
  *__p = __q;
williamr@4
   534
  return __result;
williamr@4
   535
#endif // _STLP_THREADS
williamr@4
   536
  }
williamr@4
   537
williamr@4
   538
  static void* _S_swap_ptr(void* _STLP_VOLATILE* __p, void* __q) {
williamr@4
   539
#if defined (_STLP_THREADS)
williamr@4
   540
#  if defined (_STLP_ATOMIC_EXCHANGE_PTR)
williamr@4
   541
  return _STLP_ATOMIC_EXCHANGE_PTR(__p, __q);
williamr@4
   542
#  elif defined (_STLP_ATOMIC_EXCHANGE)
williamr@4
   543
  _STLP_STATIC_ASSERT(sizeof(__stl_atomic_t) == sizeof(void*))
williamr@4
   544
  return __REINTERPRET_CAST(void*, _STLP_ATOMIC_EXCHANGE(__REINTERPRET_CAST(volatile __stl_atomic_t*, __p),
williamr@4
   545
                                                         __REINTERPRET_CAST(__stl_atomic_t, __q));
williamr@4
   546
#  elif defined (_STLP_USE_ATOMIC_SWAP_MUTEX)
williamr@4
   547
  _S_swap_lock._M_acquire_lock();
williamr@4
   548
  void *__result = *__p;
williamr@4
   549
  *__p = __q;
williamr@4
   550
  _S_swap_lock._M_release_lock();
williamr@4
   551
  return __result;
williamr@4
   552
#  else
williamr@4
   553
#    error Missing pointer atomic swap implementation
williamr@4
   554
#  endif
williamr@4
   555
#else
williamr@4
   556
  /* no thread */
williamr@4
   557
  void *__result = *__p;
williamr@4
   558
  *__p = __q;
williamr@4
   559
  return __result;
williamr@4
   560
#endif
williamr@4
   561
  }
williamr@4
   562
};
williamr@4
   563
williamr@4
   564
_STLP_TEMPLATE_NULL
williamr@4
   565
class _Atomic_swap_struct<0> {
williamr@4
   566
public:
williamr@4
   567
#if defined (_STLP_THREADS) && \
williamr@4
   568
    (!defined (_STLP_ATOMIC_EXCHANGE) || !defined (_STLP_ATOMIC_EXCHANGE_PTR)) && \
williamr@4
   569
    (defined (_STLP_PTHREADS) || defined (_STLP_UITHREADS) || defined (_STLP_OS2THREADS) || \
williamr@4
   570
     defined (_STLP_USE_PTHREAD_SPINLOCK) || defined (_STLP_NWTHREADS))
williamr@4
   571
#  define _STLP_USE_ATOMIC_SWAP_MUTEX
williamr@4
   572
  static _STLP_STATIC_MUTEX _S_swap_lock;
williamr@4
   573
#endif
williamr@4
   574
williamr@4
   575
  static __stl_atomic_t _S_swap(_STLP_VOLATILE __stl_atomic_t* __p, __stl_atomic_t __q) {
williamr@4
   576
#if defined (_STLP_THREADS)
williamr@4
   577
#  if defined (_STLP_ATOMIC_EXCHANGE)
williamr@4
   578
  return _STLP_ATOMIC_EXCHANGE(__p, __q);
williamr@4
   579
#  elif defined (_STLP_USE_ATOMIC_SWAP_MUTEX)
williamr@4
   580
  /* This should be portable, but performance is expected
williamr@4
   581
   * to be quite awful.  This really needs platform specific
williamr@4
   582
   * code.
williamr@4
   583
   */
williamr@4
   584
  _S_swap_lock._M_acquire_lock();
williamr@4
   585
  __stl_atomic_t __result = *__p;
williamr@4
   586
  *__p = __q;
williamr@4
   587
  _S_swap_lock._M_release_lock();
williamr@4
   588
  return __result;
williamr@4
   589
#  else
williamr@4
   590
#    error Missing atomic swap implementation
williamr@4
   591
#  endif
williamr@4
   592
#else
williamr@4
   593
  /* no threads */
williamr@4
   594
  __stl_atomic_t __result = *__p;
williamr@4
   595
  *__p = __q;
williamr@4
   596
  return __result;
williamr@4
   597
#endif // _STLP_THREADS
williamr@4
   598
  }
williamr@4
   599
williamr@4
   600
  static void* _S_swap_ptr(void* _STLP_VOLATILE* __p, void* __q) {
williamr@4
   601
#if defined (_STLP_THREADS)
williamr@4
   602
#  if defined (_STLP_ATOMIC_EXCHANGE_PTR)
williamr@4
   603
  return _STLP_ATOMIC_EXCHANGE_PTR(__p, __q);
williamr@4
   604
#  elif defined (_STLP_USE_ATOMIC_SWAP_MUTEX)
williamr@4
   605
  _S_swap_lock._M_acquire_lock();
williamr@4
   606
  void *__result = *__p;
williamr@4
   607
  *__p = __q;
williamr@4
   608
  _S_swap_lock._M_release_lock();
williamr@4
   609
  return __result;
williamr@4
   610
#  else
williamr@4
   611
#    error Missing pointer atomic swap implementation
williamr@4
   612
#  endif
williamr@4
   613
#else
williamr@4
   614
  /* no thread */
williamr@4
   615
  void *__result = *__p;
williamr@4
   616
  *__p = __q;
williamr@4
   617
  return __result;
williamr@4
   618
#endif
williamr@4
   619
  }
williamr@4
   620
};
williamr@4
   621
williamr@4
   622
#if defined (_STLP_MSVC) && (_STLP_MSVC == 1300)
williamr@4
   623
#  pragma warning (push)
williamr@4
   624
#  pragma warning (disable : 4189) //__use_ptr_atomic_swap initialized but not used
williamr@4
   625
#endif
williamr@4
   626
williamr@4
   627
inline __stl_atomic_t _STLP_CALL _Atomic_swap(_STLP_VOLATILE __stl_atomic_t * __p, __stl_atomic_t __q) {
williamr@4
   628
  const int __use_ptr_atomic_swap = sizeof(__stl_atomic_t) == sizeof(void*);
williamr@4
   629
  return _Atomic_swap_struct<__use_ptr_atomic_swap>::_S_swap(__p, __q);
williamr@4
   630
}
williamr@4
   631
williamr@4
   632
inline void* _STLP_CALL _Atomic_swap_ptr(void* _STLP_VOLATILE* __p, void* __q) {
williamr@4
   633
  const int __use_ptr_atomic_swap = sizeof(__stl_atomic_t) == sizeof(void*);
williamr@4
   634
  return _Atomic_swap_struct<__use_ptr_atomic_swap>::_S_swap_ptr(__p, __q);
williamr@4
   635
}
williamr@4
   636
williamr@4
   637
#if defined (_STLP_MSVC) && (_STLP_MSVC == 1300)
williamr@4
   638
#  pragma warning (pop)
williamr@4
   639
#endif
williamr@4
   640
williamr@4
   641
#if defined (_STLP_BETHREADS)
williamr@4
   642
template <int __inst>
williamr@4
   643
struct _STLP_beos_static_lock_data {
williamr@4
   644
  static bool is_init;
williamr@4
   645
  struct mutex_t : public _STLP_mutex {
williamr@4
   646
    mutex_t()
williamr@4
   647
    { _STLP_beos_static_lock_data<0>::is_init = true; }
williamr@4
   648
    ~mutex_t()
williamr@4
   649
    { _STLP_beos_static_lock_data<0>::is_init = false; }
williamr@4
   650
  };
williamr@4
   651
  static mutex_t mut;
williamr@4
   652
};
williamr@4
   653
williamr@4
   654
template <int __inst>
williamr@4
   655
bool _STLP_beos_static_lock_data<__inst>::is_init = false;
williamr@4
   656
template <int __inst>
williamr@4
   657
typename _STLP_beos_static_lock_data<__inst>::mutex_t _STLP_beos_static_lock_data<__inst>::mut;
williamr@4
   658
williamr@4
   659
inline void _STLP_mutex_base::_M_acquire_lock() {
williamr@4
   660
  if (sem == 0) {
williamr@4
   661
    // we need to initialise on demand here
williamr@4
   662
    // to prevent race conditions use our global
williamr@4
   663
    // mutex if it's available:
williamr@4
   664
    if (_STLP_beos_static_lock_data<0>::is_init) {
williamr@4
   665
      _STLP_auto_lock al(_STLP_beos_static_lock_data<0>::mut);
williamr@4
   666
      if (sem == 0) _M_initialize();
williamr@4
   667
    }
williamr@4
   668
    else {
williamr@4
   669
      // no lock available, we must still be
williamr@4
   670
      // in startup code, THERE MUST BE ONE THREAD
williamr@4
   671
      // ONLY active at this point.
williamr@4
   672
      _M_initialize();
williamr@4
   673
    }
williamr@4
   674
  }
williamr@4
   675
  status_t t;
williamr@4
   676
  t = acquire_sem(sem);
williamr@4
   677
  assert(t == B_NO_ERROR);
williamr@4
   678
}
williamr@4
   679
#endif
williamr@4
   680
williamr@4
   681
_STLP_END_NAMESPACE
williamr@4
   682
williamr@4
   683
#if !defined (_STLP_LINK_TIME_INSTANTIATION)
williamr@4
   684
#  include <stl/_threads.c>
williamr@4
   685
#endif
williamr@4
   686
williamr@4
   687
#endif /* _STLP_INTERNAL_THREADS_H */
williamr@4
   688
williamr@4
   689
// Local Variables:
williamr@4
   690
// mode:C++
williamr@4
   691
// End: