/******************************************************************** created: 2003/08/25 filename: atomic.hpp author: Matt Hurd purpose: simple atomic ops *********************************************************************/ #ifndef ATOMIC_HPP_2003825 #define ATOMIC_HPP_2003825 #include #include extern "C" { LONG __cdecl _InterlockedIncrement(LONG volatile *Addend); LONG __cdecl _InterlockedDecrement(LONG volatile *Addend); LONG __cdecl _InterlockedCompareExchange(LPLONG volatile Dest, LONG Exchange, LONG Comp); LONG __cdecl _InterlockedExchange(LPLONG volatile Target, LONG Value); LONG __cdecl _InterlockedExchangeAdd(LPLONG volatile Addend, LONG Value); } #pragma intrinsic(_InterlockedIncrement) #pragma intrinsic(_InterlockedDecrement) #pragma intrinsic(_InterlockedExchange) #pragma intrinsic(_InterlockedExchangeAdd) #pragma intrinsic(_InterlockedCompareExchange) #pragma intrinsic (_InterlockedCompareExchange) #define InterlockedCompareExchange _InterlockedCompareExchange #pragma intrinsic (_InterlockedExchange) #define InterlockedExchange _InterlockedExchange #pragma intrinsic (_InterlockedExchangeAdd) #define InterlockedExchangeAdd _InterlockedExchangeAdd #pragma intrinsic (_InterlockedIncrement) #define InterlockedIncrement _InterlockedIncrement #pragma intrinsic (_InterlockedDecrement) #define InterlockedDecrement _InterlockedDecrement namespace synch { /// \brief Simple class wrapper for raw atomic functions class atomic_op_interlocked { public: /// \brief Increment a value /// \return The incremented value. template< typename WordType> static WordType inc(WordType& v) { BOOST_STATIC_ASSERT(sizeof(WordType) == sizeof(LONG)); return static_cast( InterlockedIncrement (reinterpret_cast< LONG volatile *>( &v ) )); } /// \brief Decrement a value /// \return The deccremented value. template< typename WordType> static WordType dec(WordType& v) { BOOST_STATIC_ASSERT(sizeof(WordType) == sizeof(LONG)); return static_cast(InterlockedDecrement (reinterpret_cast< LONG volatile *>( &v ) )); } /// \brief Add a value to another /// \return The resulting value template< typename WordType, typename SomeType> static WordType add(WordType& v, SomeType rhs) { BOOST_STATIC_ASSERT(sizeof(WordType) == sizeof(LONG)); BOOST_STATIC_ASSERT(sizeof(SomeType) == sizeof(LONG)); return static_cast(InterlockedExchangeAdd (reinterpret_cast< LPLONG >(&v) ,static_cast< LONG>(rhs) )) + rhs; } /// \brief Add a value to another /// \return The resulting value template< typename WordType, typename SomeType> static WordType sub(WordType& v, SomeType rhs) { BOOST_STATIC_ASSERT(sizeof(WordType) == sizeof(LONG)); BOOST_STATIC_ASSERT(sizeof(SomeType) == sizeof(LONG)); return static_cast(InterlockedExchangeAdd (reinterpret_cast< LPLONG >(&v) ,- static_cast< LONG>(rhs) )) - rhs; } /// \brief Traditional compare and swap /// \return The original value of the destination. template< typename WordType, typename SomeType1, typename SomeType2> static WordType cas(WordType& destination, SomeType1 exchange, SomeType2 comperand) { BOOST_STATIC_ASSERT(sizeof(WordType) == sizeof(LONG)); BOOST_STATIC_ASSERT(sizeof(SomeType1) == sizeof(LONG)); BOOST_STATIC_ASSERT(sizeof(SomeType2) == sizeof(LONG)); return static_cast( InterlockedCompareExchange ( reinterpret_cast< LPLONG volatile >(&destination) , static_cast< LONG>(exchange), static_cast< LONG>(comperand) ) ); } /// \brief assign my value and return what it had /// \return The original value of the target template< typename WordType, typename SomeType> static WordType exchange(WordType& target, SomeType value) { BOOST_STATIC_ASSERT(sizeof(WordType) == sizeof(LONG)); BOOST_STATIC_ASSERT(sizeof(SomeType) == sizeof(LONG)); return static_cast ( InterlockedExchange ( reinterpret_cast< LPLONG >( &target ) , static_cast< LONG>(value) ) ); } }; /// \brief Simple class wrapper for raw atomic functions class atomic_op_simple { public: /// \brief Increment a value /// \return The incremented value. template< typename WordType> static WordType inc(WordType& v) { BOOST_STATIC_ASSERT(sizeof(WordType) == sizeof(LONG)); return ++v; } /// \brief Decrement a value /// \return The decremented value. template< typename WordType> static WordType dec(WordType& v) { BOOST_STATIC_ASSERT(sizeof(WordType) == sizeof(LONG)); return --v; } /// \brief Add a value to another template< typename WordType, typename SomeType> static WordType add(WordType& v, SomeType rhs) { BOOST_STATIC_ASSERT(sizeof(WordType) == sizeof(LONG)); BOOST_STATIC_ASSERT(sizeof(SomeType) == sizeof(LONG)); v += rhs; return v; } /// \brief Add a value to another template< typename WordType, typename SomeType> static WordType sub(WordType& v, SomeType rhs) { BOOST_STATIC_ASSERT(sizeof(WordType) == sizeof(LONG)); BOOST_STATIC_ASSERT(sizeof(SomeType) == sizeof(LONG)); v -= rhs; return v; } template< typename WordType, typename SomeType1, typename SomeType2> static WordType cas(WordType& destination, SomeType1 exchange, SomeType2 comperand) { BOOST_STATIC_ASSERT(sizeof(WordType) == sizeof(LONG)); BOOST_STATIC_ASSERT(sizeof(SomeType1) == sizeof(LONG)); BOOST_STATIC_ASSERT(sizeof(SomeType2) == sizeof(LONG)); WordType result = destination; if (comperand == destination) { destination = exchange; } return result; } /// \brief assign my value and return what it had /// \return The original value of the target template< typename WordType, typename SomeType> static WordType exchange(WordType& target, SomeType value) { BOOST_STATIC_ASSERT(sizeof(WordType) == sizeof(LONG)); BOOST_STATIC_ASSERT(sizeof(SomeType) == sizeof(LONG)); WordType result = target; target = value; return result; } }; // Some of this code was copy pasted and otherwise derived from ACE http://doc.ece.uci.edu/ // But it is hard to recognise now. Not sure what is the same that is left. // At the least it was inspired by it //============================================================================= /** * @file Atomic_Op.h * Atomic_Op.h,v 4.7 2003/02/27 00:49:25 chris Exp * @author Douglas C. Schmidt */ //============================================================================= /// \brief holds and operates on a reference to an atomic variable /// /// \pre the variable must be 32 bits /// \todo /// - Makes more sense most of the time to simply use template functions. /// I'll add them later. template < typename WordType, class Atomic = synch::atomic_op_interlocked > class atomic_holder { public: /// Initialize to c. atomic_holder (WordType& c) :value_(c) { // check that we are dealing with valid stuff BOOST_STATIC_ASSERT(sizeof(WordType) == sizeof(long)); } /// Atomically pre-increment . WordType operator++ (void) { return Atomic::inc ( value_ ); } /// Atomically post-increment . WordType operator++ (int) { return ++*this - 1; } /// Atomically increment by rhs. WordType operator+= (WordType rhs) { return Atomic::add(value_,rhs); } /// Atomically pre-decrement . WordType operator-- (void) { return Atomic::dec(value_); } /// Atomically post-decrement . WordType operator-- (int) { return --*this + 1; } // Swap another atomic holder item's value with this one // \ret returns the initial value of this object WordType exchange( WordType rhs ) { return Atomic::exchange(value_,rhs); } /// Atomically decrement by rhs. WordType operator-= (WordType rhs) { return Atomic::sub(value_, rhs); } /// Explicitly return . WordType value (void) const { return value_; } /// Explicitly return (by reference). volatile WordType &value (void) { return value_; } private: /// Current object wrapped by the atomic op. WordType& value_; }; namespace detail { /// \brief asm function to test with /// \todo /// - will not inline with naked, need to think some more about this template< typename WordType> __declspec(naked) WordType __fastcall exchange_add(volatile WordType * value, WordType rhs) { __asm { lock xadd dword ptr [ECX], EDX mov EAX, EDX ret } } /// \brief asm function to test with /// \todo /// - will not inline with naked, need to think some more about this template< typename WordType> __declspec(naked) WordType __fastcall exchange_inc(volatile WordType * value) { __asm { mov EDX, 1 lock xadd dword ptr [ECX], EDX mov EAX, EDX ret } } } } #endif