📄 _mutex.h
字号:
#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);
}
// 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) || defined (_WIN64)
// 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;
__t = __u;
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));
}
/********************** DEC CXX **************************************/
#if defined (__DECCXX) && !defined (_RWSTD_NO_ATOMIC_OPERATIONS)
// __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);
}
template <class _TypeT>
inline _TypeT* __rw_atomic_preincrement (_TypeT* &__x, bool)
{
_RWSTD_COMPILE_ASSERT (sizeof __x == sizeof (long));
return _RWSTD_REINTERPRET_CAST (_TypeT*,
__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);
}
template <class _TypeT>
inline _TypeT* __rw_atomic_predecrement (_TypeT* &__x, bool)
{
_RWSTD_COMPILE_ASSERT (sizeof __x == sizeof (long));
return _RWSTD_REINTERPRET_CAST (_TypeT*,
__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 (unsigned long&, __x),
_RWSTD_STATIC_CAST (long, __y), false);
}
template <class _TypeT>
inline _TypeT* __rw_atomic_exchange (_TypeT* &__x, const _TypeT* __y, bool)
{
_RWSTD_COMPILE_ASSERT (sizeof __x == sizeof (long));
return _RWSTD_REINTERPRET_CAST (_TypeT*,
__rw_atomic_exchange (_RWSTD_REINTERPRET_CAST (long&, __x),
_RWSTD_REINTERPRET_CAST (long, __y),
false));
}
/********************** gcc/i86 **************************************/
#elif defined (__i386__) && defined (__GNUG__)
inline
int __rw_atomic_preincrement (int &__x, bool)
{
__asm__ __volatile__ ("lock; addl $1,%0" : : "m" (__x));
return __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 __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);
}
template <class _TypeT>
inline _TypeT* __rw_atomic_preincrement (_TypeT* &__x, bool)
{
_RWSTD_COMPILE_ASSERT (sizeof __x == sizeof (long));
return _RWSTD_REINTERPRET_CAST (_TypeT*,
__rw_atomic_preincrement (_RWSTD_REINTERPRET_CAST (long&, __x),
false));
}
inline
int __rw_atomic_predecrement (int &__x, bool)
{
__asm__ __volatile__ ("lock; subl $1,%0" : : "m" (__x));
return __x;
}
inline
unsigned __rw_atomic_predecrement (unsigned &__x, bool)
{
_RWSTD_COMPILE_ASSERT (sizeof __x == sizeof (int));
return __rw_atomic_predecrement (_RWSTD_REINTERPRET_CAST (int&, __x),
false);
}
inline
long __rw_atomic_predecrement (long &__x, bool)
{
_RWSTD_COMPILE_ASSERT (sizeof __x == sizeof (int));
return __rw_atomic_predecrement (_RWSTD_REINTERPRET_CAST (int&, __x),
false);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -