/***************************************************************************
 *
 * _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
