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