X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Fstructure%2FSGAtomic.hxx;h=d4611d11c078c0e8c5ef3cbb6332d68047d7ffad;hb=08ad449774b0b80dc19b7a55d82dc25a71ce1415;hp=7bf8226f6f7b82870d5587ef252398dd796bc14c;hpb=11b16b8a86d49743a2f29570871bd8adccb51890;p=simgear.git diff --git a/simgear/structure/SGAtomic.hxx b/simgear/structure/SGAtomic.hxx index 7bf8226f..d4611d11 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 @@ -25,7 +25,10 @@ && (defined(__i386__) || defined(__x86_64__)) // No need to include something. Is a Compiler API ... # define SGATOMIC_USE_GCC4_BUILTINS -#elif defined(WIN32) +#elif defined(__sgi) && defined(_COMPILER_VERSION) && (_COMPILER_VERSION>=730) +// No need to include something. Is a Compiler API ... +# define SGATOMIC_USE_MIPSPRO_BUILTINS +#elif defined(_WIN32) # include # define SGATOMIC_USE_WIN32_INTERLOCKED #else @@ -42,6 +45,8 @@ public: { #if defined(SGATOMIC_USE_GCC4_BUILTINS) return __sync_add_and_fetch(&mValue, 1); +#elif defined(SGATOMIC_USE_MIPOSPRO_BUILTINS) + return __add_and_fetch(&mValue, 1); #elif defined(SGATOMIC_USE_WIN32_INTERLOCKED) return InterlockedIncrement(reinterpret_cast(&mValue)); #else @@ -53,6 +58,8 @@ public: { #if defined(SGATOMIC_USE_GCC4_BUILTINS) return __sync_sub_and_fetch(&mValue, 1); +#elif defined(SGATOMIC_USE_MIPOSPRO_BUILTINS) + return __sub_and_fetch(&mValue, 1); #elif defined(SGATOMIC_USE_WIN32_INTERLOCKED) return InterlockedDecrement(reinterpret_cast(&mValue)); #else @@ -65,26 +72,74 @@ public: #if defined(SGATOMIC_USE_GCC4_BUILTINS) __sync_synchronize(); return mValue; +#elif defined(SGATOMIC_USE_MIPOSPRO_BUILTINS) + __synchronize(); + return mValue; #elif defined(SGATOMIC_USE_WIN32_INTERLOCKED) return static_cast(mValue); #else 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&); SGAtomic& operator=(const SGAtomic&); #if !defined(SGATOMIC_USE_GCC4_BUILTINS) \ + && !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