123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287 |
- /* -*-c++-*- OpenThreads library, Copyright (C) 2008 The Open Thread Group
- *
- * This library is open source and may be redistributed and/or modified under
- * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
- * (at your option) any later version. The full license is in LICENSE file
- * included with this distribution, and on the openscenegraph.org website.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * OpenSceneGraph Public License for more details.
- */
- #ifndef _OPENTHREADS_ATOMIC_
- #define _OPENTHREADS_ATOMIC_
- #include <OpenThreads/Config>
- #include <OpenThreads/Exports>
- #if defined(_OPENTHREADS_ATOMIC_USE_BSD_ATOMIC)
- # include <libkern/OSAtomic.h>
- # define _OPENTHREADS_ATOMIC_USE_LIBRARY_ROUTINES
- #elif defined(_OPENTHREADS_ATOMIC_USE_GCC_BUILTINS) && defined(__i386__)
- # define _OPENTHREADS_ATOMIC_USE_LIBRARY_ROUTINES
- #elif defined(_OPENTHREADS_ATOMIC_USE_WIN32_INTERLOCKED)
- # define _OPENTHREADS_ATOMIC_USE_LIBRARY_ROUTINES
- #elif defined(_OPENTHREADS_ATOMIC_USE_SUN)
- # include <atomic.h>
- # include "Mutex"
- # include "ScopedLock"
- #elif defined(_OPENTHREADS_ATOMIC_USE_MUTEX)
- # include "Mutex"
- # include "ScopedLock"
- #endif
- #if defined(_OPENTHREADS_ATOMIC_USE_LIBRARY_ROUTINES)
- #define _OPENTHREADS_ATOMIC_INLINE
- #else
- #define _OPENTHREADS_ATOMIC_INLINE inline
- #endif
- namespace OpenThreads {
- /**
- * @class Atomic
- * @brief This class provides an atomic increment and decrement operation.
- */
- class OPENTHREAD_EXPORT_DIRECTIVE Atomic {
- public:
- Atomic(unsigned value = 0) : _value(value)
- { }
- _OPENTHREADS_ATOMIC_INLINE unsigned operator++();
- _OPENTHREADS_ATOMIC_INLINE unsigned operator--();
- _OPENTHREADS_ATOMIC_INLINE unsigned AND(unsigned value);
- _OPENTHREADS_ATOMIC_INLINE unsigned OR(unsigned value);
- _OPENTHREADS_ATOMIC_INLINE unsigned XOR(unsigned value);
- _OPENTHREADS_ATOMIC_INLINE unsigned exchange(unsigned value = 0);
- _OPENTHREADS_ATOMIC_INLINE operator unsigned() const;
- private:
- Atomic(const Atomic&);
- Atomic& operator=(const Atomic&);
- #if defined(_OPENTHREADS_ATOMIC_USE_MUTEX)
- mutable Mutex _mutex;
- #endif
- #if defined(_OPENTHREADS_ATOMIC_USE_WIN32_INTERLOCKED)
- volatile long _value;
- #elif defined(_OPENTHREADS_ATOMIC_USE_BSD_ATOMIC)
- volatile int32_t _value;
- #elif defined(_OPENTHREADS_ATOMIC_USE_SUN)
- volatile uint_t _value;
- mutable Mutex _mutex; // needed for xor
- #else
- volatile unsigned _value;
- #endif
- };
- /**
- * @class AtomicPtr
- * @brief This class provides an atomic pointer assignment using cas operations.
- */
- class OPENTHREAD_EXPORT_DIRECTIVE AtomicPtr {
- public:
- AtomicPtr(void* ptr = 0) : _ptr(ptr)
- { }
- ~AtomicPtr()
- { _ptr = 0; }
- // assigns a new pointer
- _OPENTHREADS_ATOMIC_INLINE bool assign(void* ptrNew, const void* const ptrOld);
- _OPENTHREADS_ATOMIC_INLINE void* get() const;
- private:
- AtomicPtr(const AtomicPtr&);
- AtomicPtr& operator=(const AtomicPtr&);
- #if defined(_OPENTHREADS_ATOMIC_USE_MUTEX)
- mutable Mutex _mutex;
- #endif
- void* volatile _ptr;
- };
- #if !defined(_OPENTHREADS_ATOMIC_USE_LIBRARY_ROUTINES)
- _OPENTHREADS_ATOMIC_INLINE unsigned
- Atomic::operator++()
- {
- #if defined(_OPENTHREADS_ATOMIC_USE_GCC_BUILTINS)
- return __sync_add_and_fetch(&_value, 1);
- #elif defined(_OPENTHREADS_ATOMIC_USE_MIPOSPRO_BUILTINS)
- return __add_and_fetch(&_value, 1);
- #elif defined(_OPENTHREADS_ATOMIC_USE_SUN)
- return atomic_inc_uint_nv(&_value);
- #elif defined(_OPENTHREADS_ATOMIC_USE_MUTEX)
- ScopedLock<Mutex> lock(_mutex);
- return ++_value;
- #else
- return ++_value;
- #endif
- }
- _OPENTHREADS_ATOMIC_INLINE unsigned
- Atomic::operator--()
- {
- #if defined(_OPENTHREADS_ATOMIC_USE_GCC_BUILTINS)
- return __sync_sub_and_fetch(&_value, 1);
- #elif defined(_OPENTHREADS_ATOMIC_USE_MIPOSPRO_BUILTINS)
- return __sub_and_fetch(&_value, 1);
- #elif defined(_OPENTHREADS_ATOMIC_USE_SUN)
- return atomic_dec_uint_nv(&_value);
- #elif defined(_OPENTHREADS_ATOMIC_USE_MUTEX)
- ScopedLock<Mutex> lock(_mutex);
- return --_value;
- #else
- return --_value;
- #endif
- }
- _OPENTHREADS_ATOMIC_INLINE unsigned
- Atomic::AND(unsigned value)
- {
- #if defined(_OPENTHREADS_ATOMIC_USE_GCC_BUILTINS)
- return __sync_fetch_and_and(&_value, value);
- #elif defined(_OPENTHREADS_ATOMIC_USE_MIPOSPRO_BUILTINS)
- return __and_and_fetch(&_value, value);
- #elif defined(_OPENTHREADS_ATOMIC_USE_SUN)
- return atomic_and_uint_nv(&_value, value);
- #elif defined(_OPENTHREADS_ATOMIC_USE_MUTEX)
- ScopedLock<Mutex> lock(_mutex);
- _value &= value;
- return _value;
- #else
- _value &= value;
- return _value;
- #endif
- }
- _OPENTHREADS_ATOMIC_INLINE unsigned
- Atomic::OR(unsigned value)
- {
- #if defined(_OPENTHREADS_ATOMIC_USE_GCC_BUILTINS)
- return __sync_fetch_and_or(&_value, value);
- #elif defined(_OPENTHREADS_ATOMIC_USE_MIPOSPRO_BUILTINS)
- return __or_and_fetch(&_value, value);
- #elif defined(_OPENTHREADS_ATOMIC_USE_SUN)
- return atomic_or_uint_nv(&_value, value);
- #elif defined(_OPENTHREADS_ATOMIC_USE_MUTEX)
- ScopedLock<Mutex> lock(_mutex);
- _value |= value;
- return _value;
- #else
- _value |= value;
- return _value;
- #endif
- }
- _OPENTHREADS_ATOMIC_INLINE unsigned
- Atomic::XOR(unsigned value)
- {
- #if defined(_OPENTHREADS_ATOMIC_USE_GCC_BUILTINS)
- return __sync_fetch_and_xor(&_value, value);
- #elif defined(_OPENTHREADS_ATOMIC_USE_MIPOSPRO_BUILTINS)
- return __xor_and_fetch(&_value, value);
- #elif defined(_OPENTHREADS_ATOMIC_USE_SUN)
- ScopedLock<Mutex> lock(_mutex);
- _value ^= value;
- return _value;
- #elif defined(_OPENTHREADS_ATOMIC_USE_MUTEX)
- ScopedLock<Mutex> lock(_mutex);
- _value ^= value;
- return _value;
- #else
- _value ^= value;
- return _value;
- #endif
- }
- _OPENTHREADS_ATOMIC_INLINE unsigned
- Atomic::exchange(unsigned value)
- {
- #if defined(_OPENTHREADS_ATOMIC_USE_GCC_BUILTINS)
- return __sync_lock_test_and_set(&_value, value);
- #elif defined(_OPENTHREADS_ATOMIC_USE_MIPOSPRO_BUILTINS)
- return __compare_and_swap(&_value, _value, value);
- #elif defined(_OPENTHREADS_ATOMIC_USE_SUN)
- return atomic_cas_uint(&_value, _value, value);
- #elif defined(_OPENTHREADS_ATOMIC_USE_MUTEX)
- ScopedLock<Mutex> lock(_mutex);
- unsigned oldval = _value;
- _value = value;
- return oldval;
- #else
- unsigned oldval = _value;
- _value = value;
- return oldval;
- #endif
- }
- _OPENTHREADS_ATOMIC_INLINE
- Atomic::operator unsigned() const
- {
- #if defined(_OPENTHREADS_ATOMIC_USE_GCC_BUILTINS)
- __sync_synchronize();
- return _value;
- #elif defined(_OPENTHREADS_ATOMIC_USE_MIPOSPRO_BUILTINS)
- __synchronize();
- return _value;
- #elif defined(_OPENTHREADS_ATOMIC_USE_SUN)
- membar_consumer(); // Hmm, do we need???
- return _value;
- #elif defined(_OPENTHREADS_ATOMIC_USE_MUTEX)
- ScopedLock<Mutex> lock(_mutex);
- return _value;
- #else
- return _value;
- #endif
- }
- _OPENTHREADS_ATOMIC_INLINE bool
- AtomicPtr::assign(void* ptrNew, const void* const ptrOld)
- {
- #if defined(_OPENTHREADS_ATOMIC_USE_GCC_BUILTINS)
- return __sync_bool_compare_and_swap(&_ptr, (void *)ptrOld, ptrNew);
- #elif defined(_OPENTHREADS_ATOMIC_USE_MIPOSPRO_BUILTINS)
- return __compare_and_swap((unsigned long*)&_ptr, (unsigned long)ptrOld, (unsigned long)ptrNew);
- #elif defined(_OPENTHREADS_ATOMIC_USE_SUN)
- return ptrOld == atomic_cas_ptr(&_ptr, const_cast<void*>(ptrOld), ptrNew);
- #elif defined(_OPENTHREADS_ATOMIC_USE_MUTEX)
- ScopedLock<Mutex> lock(_mutex);
- if (_ptr != ptrOld)
- return false;
- _ptr = ptrNew;
- return true;
- #else
- if (_ptr != ptrOld)
- return false;
- _ptr = ptrNew;
- return true;
- #endif
- }
- _OPENTHREADS_ATOMIC_INLINE void*
- AtomicPtr::get() const
- {
- #if defined(_OPENTHREADS_ATOMIC_USE_GCC_BUILTINS)
- __sync_synchronize();
- return _ptr;
- #elif defined(_OPENTHREADS_ATOMIC_USE_MIPOSPRO_BUILTINS)
- __synchronize();
- return _ptr;
- #elif defined(_OPENTHREADS_ATOMIC_USE_SUN)
- membar_consumer(); // Hmm, do we need???
- return _ptr;
- #elif defined(_OPENTHREADS_ATOMIC_USE_MUTEX)
- ScopedLock<Mutex> lock(_mutex);
- return _ptr;
- #else
- return _ptr;
- #endif
- }
- #endif // !defined(_OPENTHREADS_ATOMIC_USE_LIBRARY_ROUTINES)
- }
- #endif // _OPENTHREADS_ATOMIC_
|