2124 lines
53 KiB
C++
2124 lines
53 KiB
C++
/***************************************************************************
|
|
*
|
|
* _mutex.h - definitions of classes and inline functions
|
|
* for thread safety and atomic operations
|
|
*
|
|
* This is an internal header file used to implement the C++ Standard
|
|
* Library. It should never be #included directly by a program.
|
|
*
|
|
* $Id: _mutex.h 648752 2008-04-16 17:01:56Z faridz $
|
|
*
|
|
***************************************************************************
|
|
*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed
|
|
* with this work for additional information regarding copyright
|
|
* ownership. The ASF licenses this file to you under the Apache
|
|
* License, Version 2.0 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy of
|
|
* the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
* implied. See the License for the specific language governing
|
|
* permissions and limitations under the License.
|
|
*
|
|
* Copyright 1994-2008 Rogue Wave Software, Inc.
|
|
*
|
|
**************************************************************************/
|
|
|
|
#ifndef _RWSTD_RW_MUTEX_H_INCLUDED
|
|
#define _RWSTD_RW_MUTEX_H_INCLUDED
|
|
|
|
|
|
#if __GNUG__ >= 3
|
|
# pragma GCC system_header
|
|
#endif // gcc >= 3
|
|
|
|
|
|
#ifndef _RWSTD_RW_DEFS_H_INCLUDED
|
|
# include <rw/_defs.h>
|
|
#endif // _RWSTD_RW_DEFS_H_INCLUDED
|
|
|
|
|
|
#ifdef _RWSTD_REENTRANT
|
|
|
|
#ifndef _RWSTD_RW_EXCEPTION_H_INCLUDED
|
|
# include <rw/_exception.h>
|
|
#endif // _RWSTD_RW_EXCEPTION_INCLUDED
|
|
|
|
#ifndef _RWSTD_RW_ERROR_H_INCLUDED
|
|
# include <rw/_error.h>
|
|
#endif // _RWSTD_RW_ERROR_H_INCLUDED
|
|
|
|
|
|
// work around SunOS 5.{8,9}/SunPro bug (see PR #26255)
|
|
#if defined (__SunOS_5_8) || defined (__SunOS_5_9)
|
|
# undef _TIME_T
|
|
#endif // __SunOS_5_{8,9}
|
|
|
|
#if defined (_RWSTD_SOLARIS_THREADS) // assuming Solaris 2.1 or greater
|
|
|
|
// SunOS 5.7 Threads Library:
|
|
// "A statically allocated mutex does not need to be explicitly
|
|
// initialized; by default, a statically allocated mutex is initialized
|
|
// with all zeros and its scope is set to be within the calling
|
|
// process."
|
|
|
|
# include <synch.h>
|
|
# include <thread.h>
|
|
|
|
# define _RWSTD_MUTEX_INIT(mutex) mutex_init (&mutex, USYNC_THREAD, 0)
|
|
# define _RWSTD_MUTEX_DESTROY(mutex) mutex_destroy (&mutex)
|
|
# define _RWSTD_MUTEX_LOCK(mutex) mutex_lock (&mutex)
|
|
# define _RWSTD_MUTEX_UNLOCK(mutex) mutex_unlock (&mutex)
|
|
# define _RWSTD_MUTEX_T mutex_t
|
|
|
|
#elif defined (_RWSTD_POSIX_THREADS)
|
|
|
|
# if defined (_RWSTD_EDG_ECCP) && defined (_RWSTD_OS_LINUX) \
|
|
&& defined (_RWSTD_NO_LONG_LONG)
|
|
// disable error #450-D: the type "long long" is nonstandard
|
|
// when using the vanilla EDG eccp in strict mode (i.e., w/o
|
|
// long long support)
|
|
# pragma diag_suppress 450
|
|
# endif // EDG eccp on Linux
|
|
|
|
// LinuxThreads man page:
|
|
// "Variables of type pthread_mutex_t can also be initialized
|
|
// statically, using the constants PTHREAD_MUTEX_INITIALIZER
|
|
// (for fast mutexes), PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
|
|
// (for recursive mutexes), and PTHREAD_ERRORCHECK_MUTEX_INI-
|
|
// TIALIZER_NP (for error checking mutexes)."
|
|
// ...
|
|
// "Attempting to initialize an already initialized mutex results
|
|
// in undefined behavior."
|
|
|
|
# include <pthread.h>
|
|
|
|
# define _RWSTD_MUTEX_INIT(mutex) pthread_mutex_init (&mutex, 0)
|
|
# define _RWSTD_MUTEX_DESTROY(mutex) pthread_mutex_destroy (&mutex)
|
|
# define _RWSTD_MUTEX_LOCK(mutex) pthread_mutex_lock (&mutex)
|
|
# define _RWSTD_MUTEX_UNLOCK(mutex) pthread_mutex_unlock (&mutex)
|
|
# define _RWSTD_MUTEX_T pthread_mutex_t
|
|
|
|
#elif defined (_RWSTD_DCE_THREADS)
|
|
|
|
# if defined (_RWSTD_NO_DCE_PTHREAD_H)
|
|
# include <pthread.h>
|
|
# else
|
|
# include <dce/pthread.h>
|
|
# endif
|
|
|
|
# define _RWSTD_MUTEX_INIT(mutex) \
|
|
pthread_mutex_init (&mutex, pthread_mutexattr_default)
|
|
# define _RWSTD_MUTEX_DESTROY(mutex) pthread_mutex_destroy (&mutex)
|
|
# define _RWSTD_MUTEX_LOCK(mutex) pthread_mutex_lock (&mutex)
|
|
# define _RWSTD_MUTEX_UNLOCK(mutex) pthread_mutex_unlock (&mutex)
|
|
# define _RWSTD_MUTEX_T pthread_mutex_t
|
|
|
|
#elif defined (_WIN32) || defined (_WIN64)
|
|
|
|
# ifdef _RWSTD_NO_FWD_DECLARATIONS
|
|
|
|
# include <windows.h>
|
|
# define _RWSTD_MUTEX_T _RTL_CRITICAL_SECTION
|
|
|
|
# else // if defined (_RWSTD_NO_FWD_DECLARATIONS)
|
|
|
|
// avoid #including this header (MFC doesn't like it)
|
|
// # include <windows.h>
|
|
|
|
extern "C" {
|
|
|
|
// but rather declare these globals here
|
|
struct _RTL_CRITICAL_SECTION;
|
|
|
|
__declspec (dllimport) void __stdcall
|
|
InitializeCriticalSection (_RTL_CRITICAL_SECTION*);
|
|
|
|
__declspec (dllimport) void __stdcall
|
|
EnterCriticalSection (_RTL_CRITICAL_SECTION*);
|
|
|
|
__declspec (dllimport) void __stdcall
|
|
LeaveCriticalSection (_RTL_CRITICAL_SECTION*);
|
|
|
|
__declspec (dllimport) void __stdcall
|
|
DeleteCriticalSection (_RTL_CRITICAL_SECTION*);
|
|
|
|
} // extern "C"
|
|
|
|
_RWSTD_NAMESPACE (__rw) {
|
|
|
|
// fake critical section type
|
|
union __rw_critical_section {
|
|
long _C_pad; // force alignment
|
|
char _C_buf [24 /* == sizeof (_RTL_CRITICAL_SECTION) */];
|
|
};
|
|
|
|
# define _RWSTD_MUTEX_T _RW::__rw_critical_section
|
|
|
|
} // namespace __rw
|
|
|
|
|
|
# endif // _RWSTD_NO_FWD_DECLARATIONS
|
|
|
|
# ifdef _MSC_VER
|
|
extern "C" long __cdecl _InterlockedIncrement (volatile long*);
|
|
extern "C" long __cdecl _InterlockedDecrement (volatile long*);
|
|
extern "C" long __cdecl _InterlockedExchange (volatile long*, long);
|
|
# ifndef __INTEL_COMPILER
|
|
# pragma intrinsic (_InterlockedIncrement)
|
|
# pragma intrinsic (_InterlockedDecrement)
|
|
# pragma intrinsic (_InterlockedExchange)
|
|
# endif // __INTEL_COMPILER
|
|
|
|
# if _MSC_VER >= 1400 && !defined (__INTEL_COMPILER)
|
|
extern "C" short __cdecl _InterlockedIncrement16 (volatile short*);
|
|
extern "C" short __cdecl _InterlockedDecrement16 (volatile short*);
|
|
# pragma intrinsic (_InterlockedIncrement16)
|
|
# pragma intrinsic (_InterlockedDecrement16)
|
|
# endif // _MSC_VER >= 1400 && !__INTEL_COMPILER
|
|
|
|
# ifdef _M_X64
|
|
extern "C" long long __cdecl _InterlockedIncrement64 (volatile long long*);
|
|
extern "C" long long __cdecl _InterlockedDecrement64 (volatile long long*);
|
|
extern "C" long long __cdecl _InterlockedExchange64 (volatile long long*,
|
|
long long);
|
|
# ifndef __INTEL_COMPILER
|
|
# pragma intrinsic (_InterlockedIncrement64)
|
|
# pragma intrinsic (_InterlockedDecrement64)
|
|
# pragma intrinsic (_InterlockedExchange64)
|
|
# endif // __INTEL_COMPILER
|
|
# endif // _M_X64
|
|
# endif // _MSC_VER
|
|
|
|
|
|
_RWSTD_NAMESPACE (__rw) {
|
|
|
|
// Win32/64 throws non-C++ exceptions rather than returning error status
|
|
// from some system calls like most other operating systems do
|
|
|
|
inline int __rw_mutex_init (_RTL_CRITICAL_SECTION *__mutex)
|
|
{
|
|
__try {
|
|
InitializeCriticalSection (__mutex);
|
|
}
|
|
__except (1) {
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
inline int __rw_mutex_destroy (_RTL_CRITICAL_SECTION *__mutex)
|
|
{
|
|
__try {
|
|
DeleteCriticalSection (__mutex);
|
|
}
|
|
__except (1) {
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
inline int __rw_mutex_lock (_RTL_CRITICAL_SECTION *__mutex)
|
|
{
|
|
__try {
|
|
EnterCriticalSection (__mutex);
|
|
}
|
|
__except (1) {
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
inline int __rw_mutex_unlock (_RTL_CRITICAL_SECTION *__mutex)
|
|
{
|
|
__try {
|
|
LeaveCriticalSection (__mutex);
|
|
}
|
|
__except (1) {
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
# define _RWSTD_MUTEX_INIT(mutex) \
|
|
__rw_mutex_init (_RWSTD_REINTERPRET_CAST (_RTL_CRITICAL_SECTION*, &mutex))
|
|
# define _RWSTD_MUTEX_DESTROY(mutex) \
|
|
__rw_mutex_destroy (_RWSTD_REINTERPRET_CAST (_RTL_CRITICAL_SECTION*, &mutex))
|
|
# define _RWSTD_MUTEX_LOCK(mutex) \
|
|
__rw_mutex_lock (_RWSTD_REINTERPRET_CAST (_RTL_CRITICAL_SECTION*, &mutex))
|
|
# define _RWSTD_MUTEX_UNLOCK(mutex) \
|
|
__rw_mutex_unlock (_RWSTD_REINTERPRET_CAST (_RTL_CRITICAL_SECTION*, &mutex))
|
|
|
|
} // namespace __rw
|
|
|
|
#elif defined (__OS2__)
|
|
|
|
# define INCL_DOSSEMAPHORES
|
|
|
|
# include <os2.h>
|
|
|
|
# define _RWSTD_MUTEX_INIT(mutex) \
|
|
DosCreateMutexSem (0, &mutex, DC_SEM_SHARED,FALSE)
|
|
# define _RWSTD_MUTEX_DESTROY(mutex) DosCloseMutexSem (mutex)
|
|
# define _RWSTD_MUTEX_LOCK(mutex) \
|
|
DosRequestMutexSem (mutex, SEM_INDEFINITE_WAIT)
|
|
# define _RWSTD_MUTEX_UNLOCK(mutex) DosReleaseMutexSem (mutex)
|
|
# define _RWSTD_MUTEX_T HMTX
|
|
|
|
#else
|
|
# error unknown thread environment
|
|
#endif
|
|
|
|
#if defined(_RWSTD_NO_STATIC_MUTEX_INIT)
|
|
# include <new>
|
|
#endif //_RWSTD_NO_STATIC_MUTEX_INIT
|
|
|
|
|
|
#if defined (__GNUG__) && defined (__osf__)
|
|
// prevent g++ warnings about missing initializers
|
|
// see <pthread.h> for explanation of _PTHREAD_NOMETER_STATIC
|
|
# ifndef _PTHREAD_NOMETER_STATIC
|
|
# define _RWSTD_PTHREAD_MUTEX_INITIALIZER \
|
|
{ _PTHREAD_MSTATE_SLOW, _PTHREAD_MVALID | _PTHREAD_MVF_STA, \
|
|
0, 0, 0, 0, 0, 0 }
|
|
# else // if defined (_PTHREAD_NOMETER_STATIC)
|
|
# define _RWSTD_PTHREAD_MUTEX_INITIALIZER
|
|
{ 0, _PTHREAD_MVALID | _PTHREAD_MVF_STA, 0, 0, 0, 0, 0, 0 }
|
|
# endif // _PTHREAD_NOMETER_STATIC
|
|
#elif defined (__GNUG__) && defined (__sgi__)
|
|
// prevent g++ warnings about a partly bracketed initializer
|
|
# define _RWSTD_PTHREAD_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER }
|
|
#else
|
|
# define _RWSTD_PTHREAD_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
|
|
#endif
|
|
|
|
|
|
_RWSTD_NAMESPACE (__rw) {
|
|
|
|
// a using declaration (rather than a directive)
|
|
// used to work around yet another MSVC 6.0 bug
|
|
_USING (std::exception);
|
|
|
|
class __rw_thread_error : public exception
|
|
{
|
|
public:
|
|
__rw_thread_error () _THROWS (())
|
|
: exception () { }
|
|
|
|
virtual const char* what () const _THROWS (()) {
|
|
return "thread synchronization error";
|
|
}
|
|
};
|
|
|
|
|
|
// POD type with no user-defined ctor or dtor facilitates static
|
|
// initialization of mutex objects with static storage duration
|
|
// (important during library initialziation time)
|
|
class _RWSTD_EXPORT __rw_mutex_base
|
|
{
|
|
public:
|
|
|
|
void _C_acquire () {
|
|
#if !defined (__HP_aCC) || __HP_aCC > 32700
|
|
if (0 != _RWSTD_MUTEX_LOCK (_C_mutex))
|
|
_RW::__rw_throw (_RWSTD_ERROR_RUNTIME_ERROR,
|
|
"synchronization error");
|
|
#else
|
|
// working around an HP aCC 3.27 bug JAGac88738
|
|
_RWSTD_MUTEX_LOCK (_C_mutex);
|
|
#endif // !defined (__HP_aCC) || __HP_aCC > 32700
|
|
}
|
|
|
|
void _C_release ();
|
|
|
|
#ifdef _RWSTD_NO_STATIC_MUTEX_INIT
|
|
|
|
// static initialization not an option, define ctor and dtor
|
|
// and make member mutex private
|
|
|
|
__rw_mutex_base ();
|
|
|
|
~__rw_mutex_base ();
|
|
|
|
private:
|
|
|
|
// not defined
|
|
__rw_mutex_base (const __rw_mutex_base&);
|
|
__rw_mutex_base& operator= (const __rw_mutex_base&);
|
|
|
|
#endif // _RWSTD_NO_STATIC_MUTEX_INIT
|
|
|
|
_RWSTD_MUTEX_T _C_mutex; // the real thing
|
|
};
|
|
|
|
|
|
inline void __rw_mutex_base::_C_release ()
|
|
{
|
|
// we should NOT throw from here as _C_release will typically be called
|
|
// during the destruction of local objects such as __rw_guard (perhaps
|
|
// due to another exception)
|
|
_RWSTD_MUTEX_UNLOCK (_C_mutex);
|
|
}
|
|
|
|
|
|
// non-POD type, always initializes mutex data member via a function call
|
|
class _RWSTD_EXPORT __rw_mutex: public __rw_mutex_base
|
|
{
|
|
public:
|
|
|
|
#ifndef _RWSTD_NO_STATIC_MUTEX_INIT
|
|
|
|
__rw_mutex ();
|
|
|
|
~__rw_mutex ();
|
|
|
|
private:
|
|
|
|
// not defined
|
|
__rw_mutex (const __rw_mutex&);
|
|
__rw_mutex& operator= (const __rw_mutex&);
|
|
|
|
#endif // _RWSTD_NO_STATIC_MUTEX_INIT
|
|
|
|
};
|
|
|
|
|
|
#ifndef _RWSTD_NO_STATIC_MUTEX_INIT
|
|
|
|
// helper factory class - static member is guranteed to be constructed
|
|
// during static initialization; objects of this POD class are not
|
|
// destroyed during program termination (important to allow them
|
|
// to be used in dtors of other objects with static storage duration)
|
|
template <class _TypeT>
|
|
struct __rw_static_mutex
|
|
{
|
|
static __rw_mutex_base _C_mutex;
|
|
};
|
|
|
|
|
|
template <class _TypeT>
|
|
__rw_mutex_base __rw_static_mutex<_TypeT>::_C_mutex
|
|
|
|
#ifdef _RWSTD_POSIX_THREADS
|
|
|
|
= { _RWSTD_PTHREAD_MUTEX_INITIALIZER }
|
|
|
|
#endif // _RWSTD_POSIX_THREADS
|
|
;
|
|
|
|
#if _RWSTD_INSTANTIATE (_STATIC_MUTEX, _INT)
|
|
|
|
// explicitly instantiated to work around a g++ 2.95.2 bug on COFF systems
|
|
// (such as IBM AIX or DEC OSF1) where it "forgets" to do so implicitly for
|
|
// explicitly initialized static data members
|
|
_RWSTD_INSTANTIATE_1 (class _RWSTD_TI_EXPORT __rw_static_mutex<int>);
|
|
_RWSTD_INSTANTIATE_1 (class _RWSTD_TI_EXPORT __rw_static_mutex<size_t>);
|
|
|
|
#endif // _RWSTD_INSTANTIATE (_STATIC_MUTEX, _INT)
|
|
|
|
|
|
inline __rw_mutex::__rw_mutex ()
|
|
|
|
#else // if defined (_RWSTD_NO_STATIC_MUTEX_INIT)
|
|
|
|
inline __rw_mutex_base::__rw_mutex_base ()
|
|
|
|
#endif // _RWSTD_NO_STATIC_MUTEX_INIT
|
|
{
|
|
if (0 != _RWSTD_MUTEX_INIT (_C_mutex))
|
|
_RW::__rw_throw (_RWSTD_ERROR_RUNTIME_ERROR, "synchronization error");
|
|
}
|
|
|
|
#ifndef _RWSTD_NO_STATIC_MUTEX_INIT
|
|
|
|
inline __rw_mutex::~__rw_mutex ()
|
|
|
|
#else // if defined (_RWSTD_NO_STATIC_MUTEX_INIT)
|
|
|
|
inline __rw_mutex_base::~__rw_mutex_base ()
|
|
|
|
#endif // _RWSTD_NO_STATIC_MUTEX_INIT
|
|
{
|
|
_RWSTD_MUTEX_DESTROY (_C_mutex);
|
|
}
|
|
|
|
// type used in instantiating __rw_get_static_mutex
|
|
template<class _TypeT, int _IntI> struct __rw_type { };
|
|
|
|
// mutex factory function avoids problematic initialization dependencies
|
|
// introduced by definitions of mutexes with static storage duration
|
|
// instead of defining a static mutex member that may not be initialized
|
|
// before first use, a non-local class may either declare a unique type
|
|
// (enum or class) or use itself as this type, and call this template
|
|
// function with a ptr to that type to obtain an initialized mutex object
|
|
// that is the same for each unique type passed to the function
|
|
|
|
#ifndef _RWSTD_NO_STATIC_MUTEX_INIT
|
|
|
|
template <class _TypeT>
|
|
inline
|
|
__rw_mutex_base& __rw_get_static_mutex (_TypeT*)
|
|
{
|
|
// POD mutex already initialized during static initialization
|
|
return __rw_static_mutex<_TypeT>::_C_mutex;
|
|
}
|
|
|
|
#else // if defined (_RWSTD_NO_STATIC_MUTEX_INIT)
|
|
|
|
#ifdef _INLINE_WITH_STATICS
|
|
|
|
template <class _TypeT>
|
|
_INLINE_WITH_STATICS
|
|
__rw_mutex_base& __rw_get_static_mutex (_TypeT*)
|
|
|
|
#else // if !defined (_INLINE_WITH_STATICS)
|
|
|
|
template <class _TypeT>
|
|
__rw_mutex_base& __rw_get_static_mutex (_TypeT*)
|
|
|
|
#endif // _INLINE_WITH_STATICS
|
|
|
|
{
|
|
// allocate properly aligned memory for static mutex (necessary
|
|
// to prevent static local mutex from being destroyed during
|
|
// program termination)
|
|
union __mutex_buf_t {
|
|
long double __pad; // force alignment (must be first)
|
|
char __buf [sizeof (__rw_mutex_base)];
|
|
};
|
|
|
|
// using a named union to work around a bug in HP aCC 3.14.10 (JAGad03246)
|
|
static __mutex_buf_t __mutex_buf;
|
|
|
|
// initialize mutex reference to refer to the static buffer space
|
|
__rw_mutex_base &__mutex =
|
|
_RWSTD_REINTERPRET_CAST (__rw_mutex_base&, __mutex_buf);
|
|
|
|
// keep track of number of mutex initialization attempts
|
|
// although `init' may reach a value greater than 1, `mutex'
|
|
// will (should) never be multiply initialized
|
|
|
|
// implicit initialization used to prevent a g++ 2.95.2 warning on Tru64
|
|
// sorry: semantics of inline function static data are wrong (you'll wind
|
|
// up with multiple copies)
|
|
static volatile long __cntr /* = 0 */; // initialization counter
|
|
|
|
#if defined (_WIN32)
|
|
// MT safe
|
|
if (0 == __cntr && 1 == _InterlockedIncrement ((long*)&__cntr))
|
|
#else
|
|
// not so safe (volatile should help)
|
|
if (0 == __cntr && 1 == ++__cntr)
|
|
#endif // _WIN32
|
|
|
|
{
|
|
// manually initialize `mutex' via a call to placement new
|
|
new (&__mutex) __rw_mutex_base ();
|
|
|
|
// indicate that `mutex' has been fully initialized
|
|
// (unlikely that we'll have more than 1000 threads)
|
|
__cntr += 1000;
|
|
}
|
|
else
|
|
// busywait until `mutex' has been completely initialized
|
|
while (__cntr < 1000);
|
|
|
|
return __mutex;
|
|
}
|
|
|
|
#endif //_RWSTD_NO_STATIC_MUTEX_INIT
|
|
|
|
|
|
// clean up
|
|
#undef _RWSTD_MUTEX_LOCK
|
|
#undef _RWSTD_MUTEX_UNLOCK
|
|
#undef _RWSTD_MUTEX_T
|
|
|
|
|
|
// allows safe use of a mutex in the presence of exceptions
|
|
class __rw_guard
|
|
{
|
|
__rw_mutex_base *_C_mutex;
|
|
|
|
// undefined
|
|
__rw_guard& operator= (const __rw_guard&);
|
|
|
|
public:
|
|
|
|
__rw_guard (__rw_guard &__rhs)
|
|
: _C_mutex (__rhs._C_mutex) {
|
|
__rhs._C_mutex = 0;
|
|
}
|
|
|
|
__rw_guard (__rw_mutex_base &__mutex): _C_mutex (&__mutex) {
|
|
_C_mutex->_C_acquire ();
|
|
}
|
|
|
|
__rw_guard (__rw_mutex_base *__mutex): _C_mutex (__mutex) {
|
|
if (_C_mutex)
|
|
_C_mutex->_C_acquire ();
|
|
}
|
|
|
|
~__rw_guard () {
|
|
if (_C_mutex)
|
|
_C_mutex->_C_release ();
|
|
}
|
|
|
|
__rw_mutex_base* _C_set (__rw_mutex_base *__mutex) {
|
|
__rw_mutex_base *__tmp = _C_mutex;
|
|
return _C_mutex = __mutex, __tmp;
|
|
}
|
|
};
|
|
|
|
|
|
// base class for obects required to guarantee some degree of MT safety
|
|
struct _RWSTD_EXPORT __rw_synchronized
|
|
{
|
|
__rw_mutex _C_mutex;
|
|
|
|
void _C_lock () {
|
|
_C_mutex._C_acquire ();
|
|
}
|
|
|
|
void _C_unlock () {
|
|
_C_mutex._C_release ();
|
|
}
|
|
|
|
__rw_guard _C_guard () {
|
|
__rw_guard __guard (_C_mutex);
|
|
return __guard;
|
|
}
|
|
};
|
|
|
|
|
|
// helper functions for atomic value [in|de]crement and exchange
|
|
// the functions are atomic with respect to each other as long as
|
|
// they are passed the same mutex by the callers
|
|
template <class _TypeT>
|
|
inline
|
|
_TypeT __rw_atomic_preincrement (_TypeT &__t, __rw_mutex_base &__mutex)
|
|
{
|
|
_RWSTD_MT_GUARD (__mutex);
|
|
|
|
return ++__t;
|
|
}
|
|
|
|
|
|
template <class _TypeT>
|
|
inline
|
|
_TypeT __rw_atomic_predecrement (_TypeT &__t, __rw_mutex_base &__mutex)
|
|
{
|
|
_RWSTD_MT_GUARD (__mutex);
|
|
|
|
return --__t;
|
|
}
|
|
|
|
|
|
template <class _TypeT, class _TypeU>
|
|
inline
|
|
_TypeT __rw_atomic_exchange (_TypeT &__t, const _TypeU &__u,
|
|
__rw_mutex_base &__mutex)
|
|
{
|
|
_RWSTD_MT_GUARD (__mutex);
|
|
|
|
_TypeT __tmp = __t;
|
|
|
|
#ifndef _WIN64
|
|
__t = __u;
|
|
#else
|
|
// silence MSVC conversion warnings (cast breaks SunPro 5.3 and prior)
|
|
__t = _RWSTD_STATIC_CAST (_TypeT, __u);
|
|
#endif
|
|
|
|
return __tmp;
|
|
}
|
|
|
|
|
|
// for use on class statics or on namespace-scope variables
|
|
// the unused argument is only here so that all functions
|
|
// can be called from the same set of macros
|
|
|
|
template <class _TypeT>
|
|
inline
|
|
_TypeT __rw_atomic_preincrement (_TypeT &__t, bool)
|
|
{
|
|
return __rw_atomic_preincrement (__t,
|
|
__rw_get_static_mutex ((_TypeT*)0));
|
|
}
|
|
|
|
|
|
template <class _TypeT>
|
|
inline
|
|
_TypeT __rw_atomic_predecrement (_TypeT &__t, bool)
|
|
{
|
|
return __rw_atomic_predecrement (__t,
|
|
__rw_get_static_mutex ((_TypeT*)0));
|
|
}
|
|
|
|
|
|
template <class _TypeT, class _TypeU>
|
|
inline
|
|
_TypeT __rw_atomic_exchange (_TypeT &__t, const _TypeU &__u, bool)
|
|
{
|
|
return __rw_atomic_exchange (__t, __u,
|
|
__rw_get_static_mutex ((_TypeT*)0));
|
|
}
|
|
|
|
/********************** no atomic ops ********************************/
|
|
|
|
#if defined (_RWSTD_NO_ATOMIC_OPS)
|
|
|
|
// do nothing
|
|
|
|
/********************** DEC CXX **************************************/
|
|
|
|
#elif defined (__DECCXX)
|
|
|
|
} // namespace __rw
|
|
|
|
// get declarations of __ATOMIC_XXX intrinsics
|
|
# include <machine/builtins.h>
|
|
|
|
_RWSTD_NAMESPACE (__rw) {
|
|
|
|
// __ATOMIC_[DE|IN]CREMENT_[LONG|QUAD] and __ATOMIC_EXCH_[LONG|QUAD] are
|
|
// intrinsic functions declared in <machine/builtins.h> that atomically
|
|
// modify their argument and return its original value (__ATOMIC_XXX_LONG
|
|
// is misnamed -- it actually operates on an int, not a long)
|
|
|
|
inline int
|
|
__rw_atomic_preincrement (int &__x, bool)
|
|
{
|
|
return 1 + __ATOMIC_INCREMENT_LONG (&__x);
|
|
}
|
|
|
|
|
|
inline unsigned
|
|
__rw_atomic_preincrement (unsigned &__x, bool)
|
|
{
|
|
return __rw_atomic_preincrement (_RWSTD_REINTERPRET_CAST (int&, __x),
|
|
false);
|
|
}
|
|
|
|
|
|
inline long
|
|
__rw_atomic_preincrement (long &__x, bool)
|
|
{
|
|
return 1 + __ATOMIC_INCREMENT_QUAD (&__x);
|
|
}
|
|
|
|
|
|
inline unsigned long
|
|
__rw_atomic_preincrement (unsigned long &__x, bool)
|
|
{
|
|
return __rw_atomic_preincrement (_RWSTD_REINTERPRET_CAST (long&, __x),
|
|
false);
|
|
}
|
|
|
|
|
|
inline int
|
|
__rw_atomic_predecrement (int &__x, bool)
|
|
{
|
|
return __ATOMIC_DECREMENT_LONG (&__x) - 1;
|
|
}
|
|
|
|
|
|
inline unsigned
|
|
__rw_atomic_predecrement (unsigned &__x, bool)
|
|
{
|
|
return __rw_atomic_predecrement (_RWSTD_REINTERPRET_CAST (int&, __x),
|
|
false);
|
|
}
|
|
|
|
|
|
inline long
|
|
__rw_atomic_predecrement (long &__x, bool)
|
|
{
|
|
return __ATOMIC_DECREMENT_QUAD (&__x) - 1;
|
|
}
|
|
|
|
|
|
inline unsigned long
|
|
__rw_atomic_predecrement (unsigned long &__x, bool)
|
|
{
|
|
return __rw_atomic_predecrement (_RWSTD_REINTERPRET_CAST (long&, __x),
|
|
false);
|
|
}
|
|
|
|
|
|
inline int
|
|
__rw_atomic_exchange (int &__x, int __y, bool)
|
|
{
|
|
return __ATOMIC_EXCH_LONG (&__x, __y);
|
|
}
|
|
|
|
|
|
inline unsigned
|
|
__rw_atomic_exchange (unsigned &__x, unsigned __y, bool)
|
|
{
|
|
return __rw_atomic_exchange (_RWSTD_REINTERPRET_CAST (unsigned&, __x),
|
|
_RWSTD_STATIC_CAST (int, __y), false);
|
|
}
|
|
|
|
|
|
inline long
|
|
__rw_atomic_exchange (long &__x, long __y, bool)
|
|
{
|
|
return __ATOMIC_EXCH_QUAD (&__x, __y);
|
|
}
|
|
|
|
|
|
inline unsigned long
|
|
__rw_atomic_exchange (unsigned long &__x, unsigned long __y, bool)
|
|
{
|
|
return __rw_atomic_exchange (_RWSTD_REINTERPRET_CAST (long&, __x),
|
|
_RWSTD_STATIC_CAST (long, __y), false);
|
|
}
|
|
|
|
/********************** SPARC **************************************/
|
|
|
|
#elif defined (__sparc) && (defined (__SUNPRO_CC) || defined (__GNUG__))
|
|
|
|
extern "C" {
|
|
|
|
// define in assembler file "atomic-sparc.s" and "atomic-sparc64.s"
|
|
// exchange returns the original value, and add returns the incremented
|
|
// value
|
|
|
|
int __rw_atomic_xchg32 (int*, int);
|
|
int __rw_atomic_add32 (int*, int);
|
|
|
|
# if defined (_LP64)
|
|
|
|
long __rw_atomic_xchg64 (long*, long);
|
|
long __rw_atomic_add64 (long*, long);
|
|
|
|
# endif // !_LP64
|
|
|
|
} // extern "C"
|
|
|
|
|
|
inline int
|
|
__rw_atomic_preincrement (int &__x, bool)
|
|
{
|
|
_RWSTD_COMPILE_ASSERT (4 == sizeof (int));
|
|
return __rw_atomic_add32 (&__x, 1);
|
|
}
|
|
|
|
|
|
inline unsigned
|
|
__rw_atomic_preincrement (unsigned &__x, bool)
|
|
{
|
|
_RWSTD_COMPILE_ASSERT (4 == sizeof (unsigned));
|
|
return __rw_atomic_add32 (_RWSTD_REINTERPRET_CAST (int*, &__x), 1);
|
|
}
|
|
|
|
|
|
inline int
|
|
__rw_atomic_predecrement (int &__x, bool)
|
|
{
|
|
_RWSTD_COMPILE_ASSERT (4 == sizeof (int));
|
|
return __rw_atomic_add32 (&__x, -1);
|
|
}
|
|
|
|
|
|
inline unsigned
|
|
__rw_atomic_predecrement (unsigned &__x, bool)
|
|
{
|
|
_RWSTD_COMPILE_ASSERT (4 == sizeof (unsigned));
|
|
return __rw_atomic_add32 (_RWSTD_REINTERPRET_CAST (int*, &__x), -1);
|
|
}
|
|
|
|
|
|
inline int
|
|
__rw_atomic_exchange (int &__x, int __y, bool)
|
|
{
|
|
_RWSTD_COMPILE_ASSERT (4 == sizeof (int));
|
|
return __rw_atomic_xchg32 (&__x, __y);
|
|
}
|
|
|
|
|
|
inline unsigned
|
|
__rw_atomic_exchange (unsigned &__x, unsigned __y, bool)
|
|
{
|
|
_RWSTD_COMPILE_ASSERT (4 == sizeof (unsigned));
|
|
return __rw_atomic_xchg32 (_RWSTD_REINTERPRET_CAST (int*, &__x),
|
|
_RWSTD_STATIC_CAST (int, __y));
|
|
}
|
|
|
|
# if _RWSTD_INT_SIZE < _RWSTD_LONG_SIZE
|
|
|
|
inline long
|
|
__rw_atomic_preincrement (long &__x, bool)
|
|
{
|
|
_RWSTD_COMPILE_ASSERT (8 == sizeof (long));
|
|
return __rw_atomic_add64 (&__x, 1);
|
|
}
|
|
|
|
|
|
inline unsigned long
|
|
__rw_atomic_preincrement (unsigned long &__x, bool)
|
|
{
|
|
_RWSTD_COMPILE_ASSERT (8 == sizeof (unsigned long));
|
|
return __rw_atomic_add64 (_RWSTD_REINTERPRET_CAST (long*, &__x), 1);
|
|
}
|
|
|
|
|
|
|
|
inline long
|
|
__rw_atomic_predecrement (long &__x, bool)
|
|
{
|
|
_RWSTD_COMPILE_ASSERT (8 == sizeof (long));
|
|
return __rw_atomic_add64 (&__x, -1);
|
|
}
|
|
|
|
|
|
inline unsigned long
|
|
__rw_atomic_predecrement (unsigned long &__x, bool)
|
|
{
|
|
_RWSTD_COMPILE_ASSERT (8 == sizeof (unsigned long));
|
|
return __rw_atomic_add64 (_RWSTD_REINTERPRET_CAST (long*, &__x), -1);
|
|
}
|
|
|
|
|
|
inline long
|
|
__rw_atomic_exchange (long &__x, long __y, bool)
|
|
{
|
|
_RWSTD_COMPILE_ASSERT (8 == sizeof (long));
|
|
return __rw_atomic_xchg64 (&__x, __y);
|
|
}
|
|
|
|
|
|
inline unsigned long
|
|
__rw_atomic_exchange (unsigned long &__x, unsigned long __y, bool)
|
|
{
|
|
_RWSTD_COMPILE_ASSERT (8 == sizeof (unsigned long));
|
|
return __rw_atomic_xchg64 (_RWSTD_REINTERPRET_CAST (long*, &__x),
|
|
_RWSTD_STATIC_CAST (long, __y));
|
|
}
|
|
|
|
# endif // _RWSTD_INT_SIZE < _RWSTD_LONG_SIZE
|
|
|
|
/********************** AIX **************************************/
|
|
|
|
#elif defined (_AIX43) && defined (__IBMCPP__)
|
|
|
|
} // namespace __rw
|
|
|
|
#include <sys/atomic_op.h>
|
|
|
|
_RWSTD_NAMESPACE (__rw) {
|
|
|
|
inline int
|
|
__rw_atomic_preincrement (int &__x, bool)
|
|
{
|
|
return fetch_and_add (&__x, 1) + 1;
|
|
}
|
|
|
|
|
|
inline unsigned
|
|
__rw_atomic_preincrement (unsigned &__x, bool)
|
|
{
|
|
return __rw_atomic_preincrement (_RWSTD_REINTERPRET_CAST (int&, __x),
|
|
false);
|
|
}
|
|
|
|
|
|
inline int
|
|
__rw_atomic_predecrement (int &__x, bool)
|
|
{
|
|
return fetch_and_add(&__x,-1) - 1;
|
|
}
|
|
|
|
|
|
inline unsigned
|
|
__rw_atomic_predecrement (unsigned &__x, bool)
|
|
{
|
|
return __rw_atomic_predecrement (_RWSTD_REINTERPRET_CAST (int&, __x),
|
|
false);
|
|
}
|
|
|
|
|
|
inline int
|
|
__rw_atomic_exchange (int &__x, int __y, bool)
|
|
{
|
|
int __tmp;
|
|
|
|
do {
|
|
__tmp = __x;
|
|
} while (!compare_and_swap (&__x, &__tmp, __y));
|
|
|
|
return __tmp;
|
|
}
|
|
|
|
|
|
inline unsigned
|
|
__rw_atomic_exchange (unsigned &__x, unsigned __y, bool)
|
|
{
|
|
return __rw_atomic_exchange (_RWSTD_REINTERPRET_CAST (int&, __x),
|
|
_RWSTD_STATIC_CAST (int, __y), false);
|
|
}
|
|
|
|
|
|
# if _RWSTD_INT_SIZE < _RWSTD_LONG_SIZE
|
|
|
|
inline long
|
|
__rw_atomic_preincrement (long &__x, bool)
|
|
{
|
|
return fetch_and_addlp (&__x, 1) + 1;
|
|
}
|
|
|
|
|
|
inline unsigned long
|
|
__rw_atomic_preincrement (unsigned long &__x, bool)
|
|
{
|
|
return __rw_atomic_preincrement (_RWSTD_REINTERPRET_CAST (long&, __x),
|
|
false);
|
|
}
|
|
|
|
|
|
inline long
|
|
__rw_atomic_predecrement (long &__x, bool)
|
|
{
|
|
return fetch_and_addlp (&__x, -1) - 1;
|
|
}
|
|
|
|
|
|
inline unsigned long
|
|
__rw_atomic_predecrement (unsigned long &__x, bool)
|
|
{
|
|
return __rw_atomic_predecrement (_RWSTD_REINTERPRET_CAST (long&, __x),
|
|
false);
|
|
}
|
|
|
|
|
|
inline long
|
|
__rw_atomic_exchange (long &__x, long __y, bool)
|
|
{
|
|
long __tmp;
|
|
|
|
do {
|
|
__tmp = __x;
|
|
} while (!compare_and_swaplp (&__x, &__tmp, __y));
|
|
|
|
return __tmp;
|
|
}
|
|
|
|
|
|
inline unsigned long
|
|
__rw_atomic_exchange (unsigned long &__x, unsigned long __y, bool)
|
|
{
|
|
return __rw_atomic_exchange (_RWSTD_REINTERPRET_CAST (long&, __x),
|
|
_RWSTD_STATIC_CAST (long, __y), false);
|
|
}
|
|
|
|
# endif // _RWSTD_INT_SIZE < _RWSTD_LONG_SIZE
|
|
|
|
|
|
/********************** SGI **************************************/
|
|
|
|
#elif defined (__sgi) && defined (__host_mips)
|
|
|
|
} // namespace __rw
|
|
|
|
# include <mutex.h>
|
|
|
|
_RWSTD_NAMESPACE (__rw) {
|
|
|
|
|
|
inline unsigned
|
|
__rw_atomic_preincrement (unsigned &__x, bool)
|
|
{
|
|
return __add_then_test32 (&__x, 1U);
|
|
}
|
|
|
|
|
|
inline int
|
|
__rw_atomic_preincrement (int &__x, bool)
|
|
{
|
|
return __rw_atomic_preincrement (_RWSTD_REINTERPRET_CAST (unsigned&, __x),
|
|
false);
|
|
}
|
|
|
|
|
|
inline unsigned
|
|
__rw_atomic_predecrement (unsigned &__x, bool)
|
|
{
|
|
return __add_then_test32 (&__x, unsigned (-1));
|
|
}
|
|
|
|
|
|
inline int
|
|
__rw_atomic_predecrement (int &__x, bool)
|
|
{
|
|
return __rw_atomic_predecrement (_RWSTD_REINTERPRET_CAST (unsigned &, __x),
|
|
false);
|
|
}
|
|
|
|
|
|
inline unsigned
|
|
__rw_atomic_exchange (unsigned &__x, unsigned __y, bool)
|
|
{
|
|
return __test_and_set32 (&__x, __y);
|
|
}
|
|
|
|
|
|
inline int
|
|
__rw_atomic_exchange (int &__x, int __y, bool)
|
|
{
|
|
return __rw_atomic_exchange (_RWSTD_REINTERPRET_CAST (unsigned int&, __x),
|
|
_RWSTD_STATIC_CAST (unsigned int, __y), false);
|
|
}
|
|
|
|
|
|
# if _RWSTD_INT_SIZE < _RWSTD_LONG_SIZE
|
|
|
|
inline unsigned long
|
|
__rw_atomic_preincrement (unsigned long &__x, bool)
|
|
{
|
|
return __add_then_test (&__x, 1);
|
|
}
|
|
|
|
|
|
inline long
|
|
__rw_atomic_preincrement (long &__x, bool)
|
|
{
|
|
return __rw_atomic_preincrement (_RWSTD_REINTERPRET_CAST(unsigned long&,
|
|
__x),
|
|
false);
|
|
}
|
|
|
|
inline unsigned long
|
|
__rw_atomic_predecrement (unsigned long &__x, bool)
|
|
{
|
|
return __add_then_test (&__x, -1);
|
|
}
|
|
|
|
|
|
inline long
|
|
__rw_atomic_predecrement (long &__x, bool)
|
|
{
|
|
return __rw_atomic_predecrement (_RWSTD_REINTERPRET_CAST (unsigned long&,
|
|
__x),
|
|
false);
|
|
}
|
|
|
|
|
|
inline unsigned long
|
|
__rw_atomic_exchange (unsigned long &__x, unsigned long __y, bool)
|
|
{
|
|
return __test_and_set (&__x, __y);
|
|
}
|
|
|
|
|
|
inline long
|
|
__rw_atomic_exchange (long &__x, long __y, bool)
|
|
{
|
|
return __rw_atomic_exchange (_RWSTD_REINTERPRET_CAST (unsigned long&, __x),
|
|
_RWSTD_STATIC_CAST (unsigned long, __y),
|
|
false);
|
|
}
|
|
|
|
# endif // _RWSTD_INT_SIZE < _RWSTD_LONG_SIZE
|
|
|
|
/********************** PA-RISC 2.0 ************************************/
|
|
|
|
#elif defined (_PA_RISC2_0)
|
|
|
|
extern "C" {
|
|
|
|
// special constraint: the value of both the argument and the result
|
|
// must not be zero
|
|
|
|
int __rw_atomic_incr32 (int*);
|
|
int __rw_atomic_decr32 (int*);
|
|
int __rw_atomic_xchg32 (int*, int);
|
|
|
|
} // extern "C"
|
|
|
|
|
|
inline int
|
|
__rw_string_atomic_preincrement (int &__x, bool)
|
|
{
|
|
return __rw_atomic_incr32 (&__x);
|
|
}
|
|
|
|
|
|
inline unsigned
|
|
__rw_string_atomic_preincrement (unsigned &__x, bool)
|
|
{
|
|
|
|
return __rw_atomic_preincrement (_RWSTD_REINTERPRET_CAST(int&, __x),
|
|
false);
|
|
}
|
|
|
|
|
|
inline int
|
|
__rw_string_atomic_predecrement (int &__x, bool)
|
|
{
|
|
return __rw_atomic_decr32 (&__x);
|
|
}
|
|
|
|
|
|
inline unsigned
|
|
__rw_string_atomic_predecrement (unsigned &__x, bool)
|
|
{
|
|
|
|
return __rw_atomic_predecrement (_RWSTD_REINTERPRET_CAST(int&, __x),
|
|
false);
|
|
}
|
|
|
|
|
|
inline int
|
|
__rw_string_atomic_exchange (int &__x, int __y, bool)
|
|
{
|
|
return __rw_atomic_xchg32 (&__x, __y);
|
|
}
|
|
|
|
|
|
inline unsigned
|
|
__rw_string_atomic_exchange (unsigned &__x, unsigned __y, bool)
|
|
{
|
|
return __rw_string_atomic_exchange (_RWSTD_REINTERPRET_CAST(int&, __x),
|
|
_RWSTD_STATIC_CAST(int,__y),
|
|
false);
|
|
}
|
|
|
|
/********************** i386/gcc || _M_IX86 *********************************/
|
|
|
|
#elif defined (__i386__) && (defined (__GNUG__) \
|
|
|| defined (__INTEL_COMPILER)) || defined (_M_IX86)
|
|
|
|
extern "C" {
|
|
|
|
_RWSTD_EXPORT char __rw_atomic_add8 (char*, int);
|
|
_RWSTD_EXPORT short __rw_atomic_add16 (short*, short);
|
|
_RWSTD_EXPORT int __rw_atomic_add32 (int*, int);
|
|
|
|
_RWSTD_EXPORT char __rw_atomic_xchg8 (char*, char);
|
|
_RWSTD_EXPORT short __rw_atomic_xchg16 (short*, short);
|
|
_RWSTD_EXPORT int __rw_atomic_xchg32 (int*, int);
|
|
|
|
} // extern "C"
|
|
|
|
|
|
inline char
|
|
__rw_atomic_preincrement (char &__x, bool)
|
|
{
|
|
_RWSTD_COMPILE_ASSERT (1 == sizeof (char));
|
|
return __rw_atomic_add8 (&__x, +1);
|
|
}
|
|
|
|
|
|
inline signed char
|
|
__rw_atomic_preincrement (signed char &__x, bool)
|
|
{
|
|
_RWSTD_COMPILE_ASSERT (1 == sizeof (signed char));
|
|
return __rw_atomic_add8 (_RWSTD_REINTERPRET_CAST (char*, &__x), +1);
|
|
}
|
|
|
|
|
|
inline unsigned char
|
|
__rw_atomic_preincrement (unsigned char &__x, bool)
|
|
{
|
|
_RWSTD_COMPILE_ASSERT (1 == sizeof (unsigned char));
|
|
return __rw_atomic_add8 (_RWSTD_REINTERPRET_CAST (char*, &__x), +1);
|
|
}
|
|
|
|
|
|
inline short
|
|
__rw_atomic_preincrement (short &__x, bool)
|
|
{
|
|
_RWSTD_COMPILE_ASSERT (2 == sizeof (short));
|
|
|
|
#if defined (_MSC_VER) && _MSC_VER >= 1400 && !defined (__INTEL_COMPILER)
|
|
return _InterlockedIncrement16 (&__x);
|
|
#else
|
|
return __rw_atomic_add16 (&__x, +1);
|
|
#endif
|
|
}
|
|
|
|
|
|
inline unsigned short
|
|
__rw_atomic_preincrement (unsigned short &__x, bool)
|
|
{
|
|
_RWSTD_COMPILE_ASSERT (2 == sizeof (unsigned short));
|
|
|
|
#if defined (_MSC_VER) && _MSC_VER >= 1400 && !defined (__INTEL_COMPILER)
|
|
return _InterlockedIncrement16 (_RWSTD_REINTERPRET_CAST (short*, &__x));
|
|
#else
|
|
return __rw_atomic_add16 (_RWSTD_REINTERPRET_CAST (short*, &__x), +1);
|
|
#endif
|
|
}
|
|
|
|
|
|
inline int
|
|
__rw_atomic_preincrement (int &__x, bool)
|
|
{
|
|
_RWSTD_COMPILE_ASSERT (4 == sizeof (int));
|
|
|
|
#ifdef _MSC_VER
|
|
return _InterlockedIncrement (_RWSTD_REINTERPRET_CAST (long*, &__x));
|
|
#else
|
|
return __rw_atomic_add32 (&__x, 1);
|
|
#endif
|
|
}
|
|
|
|
|
|
inline unsigned int
|
|
__rw_atomic_preincrement (unsigned int &__x, bool)
|
|
{
|
|
_RWSTD_COMPILE_ASSERT (4 == sizeof (unsigned int));
|
|
|
|
#ifdef _MSC_VER
|
|
return _InterlockedIncrement (_RWSTD_REINTERPRET_CAST (long*, &__x));
|
|
#else
|
|
return __rw_atomic_add32 (_RWSTD_REINTERPRET_CAST (int*, &__x), 1);
|
|
#endif
|
|
}
|
|
|
|
|
|
inline char
|
|
__rw_atomic_predecrement (char &__x, bool)
|
|
{
|
|
_RWSTD_COMPILE_ASSERT (1 == sizeof (char));
|
|
return __rw_atomic_add8 (&__x, -1);
|
|
}
|
|
|
|
|
|
inline signed char
|
|
__rw_atomic_predecrement (signed char &__x, bool)
|
|
{
|
|
_RWSTD_COMPILE_ASSERT (1 == sizeof (signed char));
|
|
return __rw_atomic_add8 (_RWSTD_REINTERPRET_CAST (char*, &__x), -1);
|
|
}
|
|
|
|
|
|
inline unsigned char
|
|
__rw_atomic_predecrement (unsigned char &__x, bool)
|
|
{
|
|
_RWSTD_COMPILE_ASSERT (1 == sizeof (unsigned char));
|
|
return __rw_atomic_add8 (_RWSTD_REINTERPRET_CAST (char*, &__x), -1);
|
|
}
|
|
|
|
|
|
inline short
|
|
__rw_atomic_predecrement (short &__x, bool)
|
|
{
|
|
_RWSTD_COMPILE_ASSERT (2 == sizeof (short));
|
|
|
|
#if defined (_MSC_VER) && _MSC_VER >= 1400 && !defined (__INTEL_COMPILER)
|
|
return _InterlockedDecrement16 (&__x);
|
|
#else
|
|
return __rw_atomic_add16 (&__x, -1);
|
|
#endif
|
|
}
|
|
|
|
|
|
inline unsigned short
|
|
__rw_atomic_predecrement (unsigned short &__x, bool)
|
|
{
|
|
_RWSTD_COMPILE_ASSERT (2 == sizeof (unsigned short));
|
|
|
|
#if defined (_MSC_VER) && _MSC_VER >= 1400 && !defined (__INTEL_COMPILER)
|
|
return _InterlockedDecrement16 (_RWSTD_REINTERPRET_CAST (short*, &__x));
|
|
#else
|
|
return __rw_atomic_add16 (_RWSTD_REINTERPRET_CAST (short*, &__x), -1);
|
|
#endif
|
|
}
|
|
|
|
|
|
inline int
|
|
__rw_atomic_predecrement (int &__x, bool)
|
|
{
|
|
_RWSTD_COMPILE_ASSERT (4 == sizeof (int));
|
|
|
|
#ifdef _MSC_VER
|
|
return _InterlockedDecrement (_RWSTD_REINTERPRET_CAST (long*, &__x));
|
|
#else
|
|
return __rw_atomic_add32 (&__x, -1);
|
|
#endif
|
|
}
|
|
|
|
|
|
inline unsigned int
|
|
__rw_atomic_predecrement (unsigned int &__x, bool)
|
|
{
|
|
_RWSTD_COMPILE_ASSERT (4 == sizeof (unsigned int));
|
|
|
|
#ifdef _MSC_VER
|
|
return _InterlockedDecrement (_RWSTD_REINTERPRET_CAST (long*, &__x));
|
|
#else
|
|
return __rw_atomic_add32 (_RWSTD_REINTERPRET_CAST (int*, &__x), -1);
|
|
#endif
|
|
}
|
|
|
|
|
|
inline char
|
|
__rw_atomic_exchange (char &__x, char __y, bool)
|
|
{
|
|
_RWSTD_COMPILE_ASSERT (1 == sizeof (char));
|
|
return __rw_atomic_xchg8 (&__x, __y);
|
|
}
|
|
|
|
|
|
inline signed char
|
|
__rw_atomic_exchange (signed char &__x, signed char __y, bool)
|
|
{
|
|
_RWSTD_COMPILE_ASSERT (1 == sizeof (signed char));
|
|
return __rw_atomic_xchg8 (_RWSTD_REINTERPRET_CAST (char*, &__x),
|
|
_RWSTD_STATIC_CAST (char, __y));
|
|
}
|
|
|
|
|
|
inline unsigned char
|
|
__rw_atomic_exchange (unsigned char &__x, unsigned char __y, bool)
|
|
{
|
|
_RWSTD_COMPILE_ASSERT (1 == sizeof (unsigned char));
|
|
return __rw_atomic_xchg8 (_RWSTD_REINTERPRET_CAST (char*, &__x),
|
|
_RWSTD_STATIC_CAST (char, __y));
|
|
}
|
|
|
|
|
|
inline short
|
|
__rw_atomic_exchange (short &__x, short __y, bool)
|
|
{
|
|
_RWSTD_COMPILE_ASSERT (2 == sizeof (short));
|
|
return __rw_atomic_xchg16 (&__x, __y);
|
|
}
|
|
|
|
|
|
inline unsigned short
|
|
__rw_atomic_exchange (unsigned short &__x, unsigned short __y, bool)
|
|
{
|
|
_RWSTD_COMPILE_ASSERT (2 == sizeof (unsigned short));
|
|
return __rw_atomic_xchg16 (_RWSTD_REINTERPRET_CAST (short*, &__x),
|
|
_RWSTD_STATIC_CAST (short, __y));
|
|
}
|
|
|
|
|
|
inline int
|
|
__rw_atomic_exchange (int &__x, int __y, bool)
|
|
{
|
|
_RWSTD_COMPILE_ASSERT (4 == sizeof (int));
|
|
|
|
#ifdef _MSC_VER
|
|
return _InterlockedExchange (_RWSTD_REINTERPRET_CAST (long*, &__x),
|
|
_RWSTD_STATIC_CAST (long, __y));
|
|
#else
|
|
return __rw_atomic_xchg32 (&__x, __y);
|
|
#endif
|
|
}
|
|
|
|
|
|
inline unsigned int
|
|
__rw_atomic_exchange (unsigned int &__x, unsigned int __y, bool)
|
|
{
|
|
_RWSTD_COMPILE_ASSERT (4 == sizeof (unsigned int));
|
|
|
|
#ifdef _MSC_VER
|
|
return _InterlockedExchange (_RWSTD_REINTERPRET_CAST (long*, &__x),
|
|
_RWSTD_STATIC_CAST (long, __y));
|
|
#else
|
|
return __rw_atomic_xchg32 (_RWSTD_REINTERPRET_CAST (int*, &__x),
|
|
_RWSTD_STATIC_CAST (int, __y));
|
|
#endif
|
|
}
|
|
|
|
/********************** IA64/x86_64/_M_X64 *****************************/
|
|
|
|
#elif defined (__ia64) || defined (__x86_64) || defined (_M_X64)
|
|
|
|
extern "C" {
|
|
|
|
_RWSTD_EXPORT _RWSTD_INT8_T
|
|
__rw_atomic_xchg8 (_RWSTD_INT8_T*, _RWSTD_INT8_T);
|
|
|
|
_RWSTD_EXPORT _RWSTD_INT16_T
|
|
__rw_atomic_xchg16 (_RWSTD_INT16_T*, _RWSTD_INT16_T);
|
|
|
|
_RWSTD_EXPORT _RWSTD_INT32_T
|
|
__rw_atomic_xchg32 (_RWSTD_INT32_T*, _RWSTD_INT32_T);
|
|
|
|
|
|
_RWSTD_EXPORT _RWSTD_INT8_T
|
|
__rw_atomic_add8 (_RWSTD_INT8_T*, _RWSTD_INT8_T);
|
|
|
|
_RWSTD_EXPORT _RWSTD_INT16_T
|
|
__rw_atomic_add16 (_RWSTD_INT16_T*, _RWSTD_INT16_T);
|
|
|
|
_RWSTD_EXPORT _RWSTD_INT32_T
|
|
__rw_atomic_add32 (_RWSTD_INT32_T*, _RWSTD_INT32_T);
|
|
|
|
#ifdef _RWSTD_INT64_T
|
|
|
|
_RWSTD_EXPORT _RWSTD_INT64_T
|
|
__rw_atomic_xchg64 (_RWSTD_INT64_T*, _RWSTD_INT64_T);
|
|
|
|
_RWSTD_EXPORT _RWSTD_INT64_T
|
|
__rw_atomic_add64 (_RWSTD_INT64_T*, _RWSTD_INT64_T);
|
|
|
|
#endif // _RWSTD_INT64_T
|
|
|
|
} // extern "C"
|
|
|
|
|
|
inline char
|
|
__rw_atomic_preincrement (char &__x, bool)
|
|
{
|
|
_RWSTD_COMPILE_ASSERT (1 == sizeof (char));
|
|
|
|
return __rw_atomic_add8 (_RWSTD_REINTERPRET_CAST (_RWSTD_INT8_T*, &__x),
|
|
+1);
|
|
}
|
|
|
|
|
|
inline signed char
|
|
__rw_atomic_preincrement (signed char &__x, bool)
|
|
{
|
|
_RWSTD_COMPILE_ASSERT (1 == sizeof (signed char));
|
|
|
|
return __rw_atomic_add8 (_RWSTD_REINTERPRET_CAST (_RWSTD_INT8_T*, &__x),
|
|
+1);
|
|
}
|
|
|
|
|
|
inline unsigned char
|
|
__rw_atomic_preincrement (unsigned char &__x, bool)
|
|
{
|
|
_RWSTD_COMPILE_ASSERT (1 == sizeof (unsigned char));
|
|
|
|
return __rw_atomic_add8 (_RWSTD_REINTERPRET_CAST (_RWSTD_INT8_T*, &__x),
|
|
+1);
|
|
}
|
|
|
|
|
|
inline short
|
|
__rw_atomic_preincrement (short &__x, bool)
|
|
{
|
|
_RWSTD_COMPILE_ASSERT (2 == sizeof (short));
|
|
|
|
#if defined (_MSC_VER) && !defined (__INTEL_COMPILER)
|
|
return _InterlockedIncrement16 (&__x);
|
|
#else
|
|
return __rw_atomic_add16 (_RWSTD_REINTERPRET_CAST (_RWSTD_INT16_T*, &__x),
|
|
+1);
|
|
#endif
|
|
}
|
|
|
|
|
|
inline unsigned short
|
|
__rw_atomic_preincrement (unsigned short &__x, bool)
|
|
{
|
|
_RWSTD_COMPILE_ASSERT (2 == sizeof (unsigned short));
|
|
|
|
#if defined (_MSC_VER) && !defined (__INTEL_COMPILER)
|
|
return _InterlockedIncrement16 (_RWSTD_REINTERPRET_CAST (short*, &__x));
|
|
#else
|
|
return __rw_atomic_add16 (_RWSTD_REINTERPRET_CAST (_RWSTD_INT16_T*, &__x),
|
|
+1);
|
|
#endif
|
|
}
|
|
|
|
|
|
inline int
|
|
__rw_atomic_preincrement (int &__x, bool)
|
|
{
|
|
_RWSTD_COMPILE_ASSERT (4 == sizeof (int));
|
|
|
|
#ifdef _MSC_VER
|
|
return _InterlockedIncrement (_RWSTD_REINTERPRET_CAST (long*, &__x));
|
|
#else
|
|
return __rw_atomic_add32 (_RWSTD_REINTERPRET_CAST (_RWSTD_INT32_T*, &__x),
|
|
+1);
|
|
#endif
|
|
}
|
|
|
|
|
|
inline unsigned int
|
|
__rw_atomic_preincrement (unsigned int &__x, bool)
|
|
{
|
|
_RWSTD_COMPILE_ASSERT (4 == sizeof (unsigned int));
|
|
|
|
#ifdef _MSC_VER
|
|
return _InterlockedIncrement (_RWSTD_REINTERPRET_CAST (long*, &__x));
|
|
#else
|
|
return __rw_atomic_add32 (_RWSTD_REINTERPRET_CAST (_RWSTD_INT32_T*, &__x),
|
|
+1);
|
|
#endif
|
|
}
|
|
|
|
|
|
#if 4 < _RWSTD_LONG_SIZE
|
|
|
|
inline long
|
|
__rw_atomic_preincrement (long &__x, bool)
|
|
{
|
|
_RWSTD_COMPILE_ASSERT (8 == sizeof (long));
|
|
|
|
return __rw_atomic_add64 (_RWSTD_REINTERPRET_CAST (_RWSTD_INT64_T*, &__x),
|
|
+1);
|
|
}
|
|
|
|
|
|
inline unsigned long
|
|
__rw_atomic_preincrement (unsigned long &__x, bool)
|
|
{
|
|
_RWSTD_COMPILE_ASSERT (8 == sizeof (unsigned long));
|
|
|
|
return __rw_atomic_add64 (_RWSTD_REINTERPRET_CAST (_RWSTD_INT64_T*, &__x),
|
|
+1);
|
|
}
|
|
|
|
#endif // _RWSTD_LONG_SIZE
|
|
|
|
|
|
#ifdef _RWSTD_LONG_LONG
|
|
# if _RWSTD_LLONG_SIZE > _RWSTD_LONG_SIZE
|
|
|
|
inline _RWSTD_LONG_LONG
|
|
__rw_atomic_preincrement (_RWSTD_LONG_LONG &__x, bool)
|
|
{
|
|
_RWSTD_COMPILE_ASSERT (8 == sizeof (_RWSTD_LONG_LONG));
|
|
|
|
#ifdef _MSC_VER
|
|
return _InterlockedIncrement64 (_RWSTD_REINTERPRET_CAST (__int64*, &__x));
|
|
#else
|
|
return __rw_atomic_add64 (_RWSTD_REINTERPRET_CAST (_RWSTD_INT64_T*, &__x),
|
|
+1);
|
|
#endif
|
|
}
|
|
|
|
|
|
inline unsigned _RWSTD_LONG_LONG
|
|
__rw_atomic_preincrement (unsigned _RWSTD_LONG_LONG &__x, bool)
|
|
{
|
|
_RWSTD_COMPILE_ASSERT (8 == sizeof (unsigned _RWSTD_LONG_LONG));
|
|
|
|
#ifdef _MSC_VER
|
|
return _InterlockedIncrement64 (_RWSTD_REINTERPRET_CAST (__int64*, &__x));
|
|
#else
|
|
return __rw_atomic_add64 (_RWSTD_REINTERPRET_CAST (_RWSTD_INT64_T*, &__x),
|
|
+1);
|
|
#endif
|
|
}
|
|
|
|
# endif // _RWSTD_LLONG_SIZE > _RWSTD_LONG_SIZE
|
|
#endif // _RWSTD_LONG_LONG
|
|
|
|
|
|
inline char
|
|
__rw_atomic_predecrement (char &__x, bool)
|
|
{
|
|
_RWSTD_COMPILE_ASSERT (1 == sizeof (char));
|
|
|
|
return __rw_atomic_add8 (_RWSTD_REINTERPRET_CAST (_RWSTD_INT8_T*, &__x),
|
|
-1);
|
|
}
|
|
|
|
|
|
inline signed char
|
|
__rw_atomic_predecrement (signed char &__x, bool)
|
|
{
|
|
_RWSTD_COMPILE_ASSERT (1 == sizeof (signed char));
|
|
|
|
return __rw_atomic_add8 (_RWSTD_REINTERPRET_CAST (_RWSTD_INT8_T*, &__x),
|
|
-1);
|
|
}
|
|
|
|
|
|
inline unsigned char
|
|
__rw_atomic_predecrement (unsigned char &__x, bool)
|
|
{
|
|
_RWSTD_COMPILE_ASSERT (1 == sizeof (unsigned char));
|
|
|
|
return __rw_atomic_add8 (_RWSTD_REINTERPRET_CAST (_RWSTD_INT8_T*, &__x),
|
|
-1);
|
|
}
|
|
|
|
|
|
inline short
|
|
__rw_atomic_predecrement (short &__x, bool)
|
|
{
|
|
_RWSTD_COMPILE_ASSERT (2 == sizeof (short));
|
|
|
|
#if defined (_MSC_VER) && !defined (__INTEL_COMPILER)
|
|
return _InterlockedDecrement16 (&__x);
|
|
#else
|
|
return __rw_atomic_add16 (_RWSTD_REINTERPRET_CAST (_RWSTD_INT16_T*, &__x),
|
|
-1);
|
|
#endif
|
|
}
|
|
|
|
|
|
inline unsigned short
|
|
__rw_atomic_predecrement (unsigned short &__x, bool)
|
|
{
|
|
_RWSTD_COMPILE_ASSERT (2 == sizeof (unsigned short));
|
|
|
|
#if defined (_MSC_VER) && !defined (__INTEL_COMPILER)
|
|
return _InterlockedDecrement16 (_RWSTD_REINTERPRET_CAST (short*, &__x));
|
|
#else
|
|
return __rw_atomic_add16 (_RWSTD_REINTERPRET_CAST (_RWSTD_INT16_T*, &__x),
|
|
-1);
|
|
#endif
|
|
}
|
|
|
|
|
|
inline int
|
|
__rw_atomic_predecrement (int &__x, bool)
|
|
{
|
|
_RWSTD_COMPILE_ASSERT (4 == sizeof (int));
|
|
|
|
#ifdef _MSC_VER
|
|
return _InterlockedDecrement (_RWSTD_REINTERPRET_CAST (long*, &__x));
|
|
#else
|
|
return __rw_atomic_add32 (_RWSTD_REINTERPRET_CAST (_RWSTD_INT32_T*, &__x),
|
|
-1);
|
|
#endif
|
|
}
|
|
|
|
|
|
inline unsigned int
|
|
__rw_atomic_predecrement (unsigned int &__x, bool)
|
|
{
|
|
_RWSTD_COMPILE_ASSERT (4 == sizeof (unsigned int));
|
|
|
|
#ifdef _MSC_VER
|
|
return _InterlockedDecrement (_RWSTD_REINTERPRET_CAST (long*, &__x));
|
|
#else
|
|
return __rw_atomic_add32 (_RWSTD_REINTERPRET_CAST (_RWSTD_INT32_T*, &__x),
|
|
-1);
|
|
#endif
|
|
}
|
|
|
|
|
|
#if 4 < _RWSTD_LONG_SIZE
|
|
|
|
inline long
|
|
__rw_atomic_predecrement (long &__x, bool)
|
|
{
|
|
_RWSTD_COMPILE_ASSERT (8 == sizeof (long));
|
|
|
|
return __rw_atomic_add64 (_RWSTD_REINTERPRET_CAST (_RWSTD_INT64_T*, &__x),
|
|
-1);
|
|
}
|
|
|
|
|
|
inline unsigned long
|
|
__rw_atomic_predecrement (unsigned long &__x, bool)
|
|
{
|
|
_RWSTD_COMPILE_ASSERT (8 == sizeof (unsigned long));
|
|
|
|
return __rw_atomic_add64 (_RWSTD_REINTERPRET_CAST (_RWSTD_INT64_T*, &__x),
|
|
-1);
|
|
}
|
|
|
|
#endif // _RWSTD_LONG_SIZE
|
|
|
|
|
|
#ifdef _RWSTD_LONG_LONG
|
|
# if _RWSTD_LLONG_SIZE > _RWSTD_LONG_SIZE
|
|
|
|
inline _RWSTD_LONG_LONG
|
|
__rw_atomic_predecrement (_RWSTD_LONG_LONG &__x, bool)
|
|
{
|
|
_RWSTD_COMPILE_ASSERT (8 == sizeof (_RWSTD_LONG_LONG));
|
|
|
|
#ifdef _MSC_VER
|
|
return _InterlockedDecrement64 (_RWSTD_REINTERPRET_CAST (__int64*, &__x));
|
|
#else
|
|
return __rw_atomic_add64 (_RWSTD_REINTERPRET_CAST (_RWSTD_INT64_T*, &__x),
|
|
-1);
|
|
#endif
|
|
}
|
|
|
|
|
|
inline unsigned _RWSTD_LONG_LONG
|
|
__rw_atomic_predecrement (unsigned _RWSTD_LONG_LONG &__x, bool)
|
|
{
|
|
_RWSTD_COMPILE_ASSERT (8 == sizeof (unsigned _RWSTD_LONG_LONG));
|
|
|
|
#ifdef _MSC_VER
|
|
return _InterlockedDecrement64 (_RWSTD_REINTERPRET_CAST (__int64*, &__x));
|
|
#else
|
|
return __rw_atomic_add64 (_RWSTD_REINTERPRET_CAST (_RWSTD_INT64_T*, &__x),
|
|
-1);
|
|
#endif
|
|
}
|
|
|
|
# endif // _RWSTD_LLONG_SIZE > _RWSTD_LONG_SIZE
|
|
#endif // _RWSTD_LONG_LONG
|
|
|
|
|
|
inline char
|
|
__rw_atomic_exchange (char &__x, char __y, bool)
|
|
{
|
|
_RWSTD_COMPILE_ASSERT (1 == sizeof (char));
|
|
|
|
return __rw_atomic_xchg8 (_RWSTD_REINTERPRET_CAST (_RWSTD_INT8_T*, &__x),
|
|
_RWSTD_STATIC_CAST (_RWSTD_INT8_T, __y));
|
|
}
|
|
|
|
|
|
inline signed char
|
|
__rw_atomic_exchange (signed char &__x, signed char __y, bool)
|
|
{
|
|
_RWSTD_COMPILE_ASSERT (1 == sizeof (signed char));
|
|
|
|
return __rw_atomic_xchg8 (_RWSTD_REINTERPRET_CAST (_RWSTD_INT8_T*, &__x),
|
|
_RWSTD_STATIC_CAST (_RWSTD_INT8_T, __y));
|
|
}
|
|
|
|
|
|
inline unsigned char
|
|
__rw_atomic_exchange (unsigned char &__x, unsigned char __y, bool)
|
|
{
|
|
_RWSTD_COMPILE_ASSERT (1 == sizeof (unsigned char));
|
|
|
|
return __rw_atomic_xchg8 (_RWSTD_REINTERPRET_CAST (_RWSTD_INT8_T*, &__x),
|
|
_RWSTD_STATIC_CAST (_RWSTD_INT8_T, __y));
|
|
}
|
|
|
|
|
|
inline short
|
|
__rw_atomic_exchange (short &__x, short __y, bool)
|
|
{
|
|
_RWSTD_COMPILE_ASSERT (2 == sizeof (short));
|
|
|
|
return __rw_atomic_xchg16 (_RWSTD_REINTERPRET_CAST (_RWSTD_INT16_T*, &__x),
|
|
_RWSTD_STATIC_CAST (_RWSTD_INT16_T, __y));
|
|
}
|
|
|
|
|
|
inline unsigned short
|
|
__rw_atomic_exchange (unsigned short &__x, unsigned short __y, bool)
|
|
{
|
|
_RWSTD_COMPILE_ASSERT (2 == sizeof (unsigned short));
|
|
|
|
return __rw_atomic_xchg16 (_RWSTD_REINTERPRET_CAST (_RWSTD_INT16_T*, &__x),
|
|
_RWSTD_STATIC_CAST (_RWSTD_INT16_T, __y));
|
|
}
|
|
|
|
|
|
inline int
|
|
__rw_atomic_exchange (int &__x, int __y, bool)
|
|
{
|
|
_RWSTD_COMPILE_ASSERT (4 == sizeof (int));
|
|
|
|
#ifdef _MSC_VER
|
|
return _InterlockedExchange (_RWSTD_REINTERPRET_CAST (long*, &__x),
|
|
_RWSTD_STATIC_CAST (long, __y));
|
|
#else
|
|
return __rw_atomic_xchg32 (_RWSTD_REINTERPRET_CAST (_RWSTD_INT32_T*, &__x),
|
|
_RWSTD_STATIC_CAST (_RWSTD_INT32_T, __y));
|
|
#endif
|
|
}
|
|
|
|
|
|
inline unsigned int
|
|
__rw_atomic_exchange (unsigned int &__x, unsigned int __y, bool)
|
|
{
|
|
_RWSTD_COMPILE_ASSERT (4 == sizeof (unsigned int));
|
|
|
|
#ifdef _MSC_VER
|
|
return _InterlockedExchange (_RWSTD_REINTERPRET_CAST (long*, &__x),
|
|
_RWSTD_STATIC_CAST (long, __y));
|
|
#else
|
|
return __rw_atomic_xchg32 (_RWSTD_REINTERPRET_CAST (_RWSTD_INT32_T*, &__x),
|
|
_RWSTD_STATIC_CAST (_RWSTD_INT32_T, __y));
|
|
#endif
|
|
}
|
|
|
|
|
|
# if 4 < _RWSTD_LONG_SIZE
|
|
|
|
inline long
|
|
__rw_atomic_exchange (long &__x, long __y, bool)
|
|
{
|
|
_RWSTD_COMPILE_ASSERT (8 == sizeof (long));
|
|
|
|
return __rw_atomic_xchg64 (_RWSTD_REINTERPRET_CAST (_RWSTD_INT64_T*, &__x),
|
|
_RWSTD_STATIC_CAST (_RWSTD_INT64_T, __y));
|
|
}
|
|
|
|
|
|
inline unsigned long
|
|
__rw_atomic_exchange (unsigned long &__x, unsigned long __y, bool)
|
|
{
|
|
_RWSTD_COMPILE_ASSERT (8 == sizeof (unsigned long));
|
|
|
|
return __rw_atomic_xchg64 (_RWSTD_REINTERPRET_CAST (_RWSTD_INT64_T*, &__x),
|
|
_RWSTD_STATIC_CAST (_RWSTD_INT64_T, __y));
|
|
}
|
|
|
|
# endif // _RWSTD_LONG_SIZE == _RWSTD_INT_SIZE
|
|
|
|
|
|
#ifdef _RWSTD_LONG_LONG
|
|
# if _RWSTD_LLONG_SIZE > _RWSTD_LONG_SIZE
|
|
|
|
inline _RWSTD_LONG_LONG
|
|
__rw_atomic_exchange (_RWSTD_LONG_LONG &__x, _RWSTD_LONG_LONG __y, bool)
|
|
{
|
|
_RWSTD_COMPILE_ASSERT (8 == sizeof (_RWSTD_LONG_LONG));
|
|
|
|
#ifdef _MSC_VER
|
|
return _InterlockedExchange64 (_RWSTD_REINTERPRET_CAST (__int64*, &__x),
|
|
_RWSTD_STATIC_CAST (__int64, __y));
|
|
#else
|
|
return __rw_atomic_xchg64 (_RWSTD_REINTERPRET_CAST (_RWSTD_INT64_T*, &__x),
|
|
_RWSTD_STATIC_CAST (_RWSTD_INT64_T, __y));
|
|
#endif
|
|
}
|
|
|
|
|
|
inline unsigned _RWSTD_LONG_LONG
|
|
__rw_atomic_exchange (unsigned _RWSTD_LONG_LONG &__x,
|
|
unsigned _RWSTD_LONG_LONG __y, bool)
|
|
{
|
|
_RWSTD_COMPILE_ASSERT (8 == sizeof (unsigned _RWSTD_LONG_LONG));
|
|
|
|
#ifdef _MSC_VER
|
|
return _InterlockedExchange64 (_RWSTD_REINTERPRET_CAST (__int64*, &__x),
|
|
_RWSTD_STATIC_CAST (__int64, __y));
|
|
#else
|
|
return __rw_atomic_xchg64 (_RWSTD_REINTERPRET_CAST (_RWSTD_INT64_T*, &__x),
|
|
_RWSTD_STATIC_CAST (_RWSTD_INT64_T, __y));
|
|
#endif
|
|
}
|
|
|
|
# endif // _RWSTD_LLONG_SIZE > _RWSTD_LONG_SIZE
|
|
#endif // _RWSTD_LONG_LONG
|
|
|
|
|
|
#elif !defined (_RWSTD_NO_ATOMIC_OPS)
|
|
# define _RWSTD_NO_ATOMIC_OPS
|
|
#endif // _RWSTD_NO_ATOMIC_OPS
|
|
|
|
|
|
/********************** generic bool functions ************************/
|
|
|
|
#ifndef _RWSTD_NO_BOOL
|
|
|
|
# if _RWSTD_BOOL_SIZE == _RWSTD_CHAR_SIZE
|
|
# define _RWSTD_BOOL_TYPE char
|
|
# elif _RWSTD_BOOL_SIZE == _RWSTD_SHORT_SIZE
|
|
# define _RWSTD_BOOL_TYPE short
|
|
# elif _RWSTD_BOOL_SIZE == _RWSTD_INT_SIZE
|
|
# define _RWSTD_BOOL_TYPE int
|
|
# endif
|
|
|
|
# ifdef _RWSTD_BOOL_TYPE
|
|
|
|
inline bool
|
|
__rw_atomic_exchange (bool &__x, bool __y, bool)
|
|
{
|
|
return 0 != __rw_atomic_exchange (
|
|
_RWSTD_REINTERPRET_CAST (_RWSTD_BOOL_TYPE&, __x),
|
|
_RWSTD_STATIC_CAST (_RWSTD_BOOL_TYPE, __y),
|
|
false);
|
|
}
|
|
|
|
# undef _RWSTD_BOOL_TYPE
|
|
# endif // _RWSTD_BOOL_TYPE
|
|
|
|
#endif // _RWSTD_NO_BOOL
|
|
|
|
|
|
/********************** generic long functions ************************/
|
|
|
|
#if _RWSTD_LONG_SIZE == _RWSTD_INT_SIZE
|
|
|
|
inline long
|
|
__rw_atomic_preincrement (long &__x, bool)
|
|
{
|
|
return __rw_atomic_preincrement (_RWSTD_REINTERPRET_CAST (int&, __x),
|
|
false);
|
|
}
|
|
|
|
inline unsigned long
|
|
__rw_atomic_preincrement (unsigned long &__x, bool)
|
|
{
|
|
return __rw_atomic_preincrement (_RWSTD_REINTERPRET_CAST (int&, __x),
|
|
false);
|
|
}
|
|
|
|
inline long
|
|
__rw_atomic_predecrement (long &__x, bool)
|
|
{
|
|
return __rw_atomic_predecrement (_RWSTD_REINTERPRET_CAST (int&, __x),
|
|
false);
|
|
}
|
|
|
|
inline unsigned long
|
|
__rw_atomic_predecrement (unsigned long &__x, bool)
|
|
{
|
|
return __rw_atomic_predecrement (_RWSTD_REINTERPRET_CAST (int&, __x),
|
|
false);
|
|
}
|
|
|
|
inline long
|
|
__rw_atomic_exchange (long &__x, long __y, bool)
|
|
{
|
|
return __rw_atomic_exchange (_RWSTD_REINTERPRET_CAST (int&, __x),
|
|
_RWSTD_STATIC_CAST (int, __y),
|
|
false);
|
|
}
|
|
|
|
inline unsigned long
|
|
__rw_atomic_exchange (unsigned long &__x,
|
|
unsigned long __y, bool)
|
|
{
|
|
return __rw_atomic_exchange (_RWSTD_REINTERPRET_CAST (int&, __x),
|
|
_RWSTD_STATIC_CAST (int, __y),
|
|
false);
|
|
}
|
|
|
|
#endif // _RWSTD_LONG_SIZE == _RWSTD_INT_SIZE
|
|
|
|
/********************** generic long long functions *******************/
|
|
|
|
#ifdef _RWSTD_LONG_LONG
|
|
# if _RWSTD_LLONG_SIZE == _RWSTD_LONG_SIZE
|
|
|
|
inline _RWSTD_LONG_LONG
|
|
__rw_atomic_preincrement (_RWSTD_LONG_LONG &__x, bool)
|
|
{
|
|
return __rw_atomic_preincrement (_RWSTD_REINTERPRET_CAST (long&, __x),
|
|
false);
|
|
}
|
|
|
|
inline unsigned _RWSTD_LONG_LONG
|
|
__rw_atomic_preincrement (unsigned _RWSTD_LONG_LONG &__x, bool)
|
|
{
|
|
return __rw_atomic_preincrement (_RWSTD_REINTERPRET_CAST (long&, __x),
|
|
false);
|
|
}
|
|
|
|
inline _RWSTD_LONG_LONG
|
|
__rw_atomic_predecrement (_RWSTD_LONG_LONG &__x, bool)
|
|
{
|
|
return __rw_atomic_predecrement (_RWSTD_REINTERPRET_CAST (long&, __x),
|
|
false);
|
|
}
|
|
|
|
inline unsigned _RWSTD_LONG_LONG
|
|
__rw_atomic_predecrement (unsigned _RWSTD_LONG_LONG &__x, bool)
|
|
{
|
|
return __rw_atomic_predecrement (_RWSTD_REINTERPRET_CAST (long&, __x),
|
|
false);
|
|
}
|
|
|
|
inline _RWSTD_LONG_LONG
|
|
__rw_atomic_exchange (_RWSTD_LONG_LONG &__x, _RWSTD_LONG_LONG __y, bool)
|
|
{
|
|
return __rw_atomic_exchange (_RWSTD_REINTERPRET_CAST (long&, __x),
|
|
_RWSTD_STATIC_CAST (long, __y),
|
|
false);
|
|
}
|
|
|
|
inline unsigned _RWSTD_LONG_LONG
|
|
__rw_atomic_exchange (unsigned _RWSTD_LONG_LONG &__x,
|
|
unsigned _RWSTD_LONG_LONG __y, bool)
|
|
{
|
|
return __rw_atomic_exchange (_RWSTD_REINTERPRET_CAST (long&, __x),
|
|
_RWSTD_STATIC_CAST (long, __y),
|
|
false);
|
|
}
|
|
|
|
# endif // _RWSTD_LLONG_SIZE == _RWSTD_LONG_SIZE
|
|
#endif // _RWSTD_LONG_LONG
|
|
|
|
|
|
} // namespace __rw
|
|
|
|
|
|
#else // if !defined (_RWSTD_REENTRANT)
|
|
|
|
|
|
_RWSTD_NAMESPACE (__rw) {
|
|
|
|
// atomic in a single-threaded environment
|
|
template <class _TypeT, class _TypeU>
|
|
inline
|
|
_TypeT __rw_atomic_exchange (_TypeT &__t, const _TypeU &__u, bool)
|
|
{
|
|
_TypeT __tmp = __t;
|
|
__t = _TypeT (__u);
|
|
return __tmp;
|
|
}
|
|
|
|
|
|
// dummy classes used as a base class in single-threaded environments
|
|
|
|
struct __rw_mutex_base
|
|
{
|
|
void _C_acquire () { }
|
|
|
|
void _C_release () { }
|
|
};
|
|
|
|
|
|
struct _RWSTD_EXPORT __rw_mutex: public __rw_mutex_base
|
|
{
|
|
};
|
|
|
|
|
|
struct __rw_guard
|
|
{
|
|
__rw_guard (__rw_mutex_base&) { }
|
|
|
|
__rw_guard (__rw_mutex_base*) { }
|
|
|
|
__rw_mutex_base* _C_set (__rw_mutex_base*) {
|
|
return 0;
|
|
}
|
|
};
|
|
|
|
|
|
struct __rw_synchronized
|
|
{
|
|
// static so that it takes up no space
|
|
static _RWSTD_EXPORT __rw_mutex _C_mutex;
|
|
|
|
void _C_lock () { }
|
|
|
|
void _C_unlock () { }
|
|
|
|
__rw_guard _C_guard () {
|
|
return __rw_guard (_C_mutex);
|
|
}
|
|
};
|
|
|
|
|
|
} // namespace __rw
|
|
|
|
|
|
#endif // _RWSTD_REENTRANT
|
|
|
|
|
|
_RWSTD_NAMESPACE (__rw) {
|
|
|
|
// available in all environments (ST and MT), used along with
|
|
// __rw_atomic_exchange<>() from conditional expressions in iostreams
|
|
template <class _TypeT, class _TypeU>
|
|
inline
|
|
_TypeT __rw_ordinary_exchange (_TypeT &__t, const _TypeU &__u)
|
|
{
|
|
_TypeT __tmp = __t;
|
|
__t = __u;
|
|
return __tmp;
|
|
}
|
|
|
|
} // namespace __rw
|
|
|
|
|
|
#endif // _RWSTD_RW_MUTEX_H_INCLUDED
|