X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Fstructure%2FSGAtomic.hxx;h=a7977fc31408483332cb004c026a59bd6cbb2d3c;hb=7e7d877874fcd67cad0152bd1a2a073e0337235f;hp=4029f3527fb91938f0871ee8670e454118faf93e;hpb=0c8358ae67e218b3cd3a0332bd9d8c7be0521af3;p=simgear.git diff --git a/simgear/structure/SGAtomic.hxx b/simgear/structure/SGAtomic.hxx index 4029f352..a7977fc3 100644 --- a/simgear/structure/SGAtomic.hxx +++ b/simgear/structure/SGAtomic.hxx @@ -1,6 +1,6 @@ /* -*-c++-*- * - * Copyright (C) 2005-2006 Mathias Froehlich + * Copyright (C) 2005-2009 Mathias Froehlich * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -81,7 +81,25 @@ public: SGGuard lock(mMutex); return mValue; #endif - } + } + + bool compareAndExchange(unsigned oldValue, unsigned newValue) + { +#if defined(SGATOMIC_USE_GCC4_BUILTINS) + return __sync_bool_compare_and_swap(&mValue, oldValue, newValue); +#elif defined(SGATOMIC_USE_MIPOSPRO_BUILTINS) + return __compare_and_swap(&mValue, oldValue, newValue); +#elif defined(SGATOMIC_USE_WIN32_INTERLOCKED) + long volatile* lvPtr = reinterpret_cast(&mValue); + return oldValue == InterlockedCompareExchange(lvPtr, newValue, oldValue); +#else + SGGuard lock(mMutex); + if (mValue != oldValue) + return false; + mValue = newValue; + return true; +#endif + } private: SGAtomic(const SGAtomic&); @@ -91,11 +109,37 @@ private: && !defined(SGATOMIC_USE_MIPOSPRO_BUILTINS) \ && !defined(SGATOMIC_USE_WIN32_INTERLOCKED) mutable SGMutex mMutex; -#endif -#ifdef SGATOMIC_USE_WIN32_INTERLOCKED - __declspec(align(32)) #endif unsigned mValue; }; +namespace simgear +{ +// Typesafe wrapper around SGSwappable +template +class Swappable : private SGAtomic +{ +public: + Swappable(const T& value) : SGAtomic(static_cast(value)) + { + } + T operator() () const + { + return static_cast(SGAtomic::operator unsigned ()); + } + Swappable& operator=(const Swappable& rhs) + { + for (unsigned oldval = unsigned(*this); + !compareAndExchange(oldval, unsigned(rhs)); + oldval = unsigned(*this)) + ; + return *this; + } + bool compareAndSwap(const T& oldVal, const T& newVal) + { + return SGAtomic::compareAndExchange(static_cast(oldVal), + static_cast(newVal)); + } +}; +} #endif