00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifndef SGAtomic_HXX
00022 #define SGAtomic_HXX
00023
00024 #if defined(__GNUC__) && (4 <= __GNUC__) && (1 <= __GNUC_MINOR__) \
00025 && (defined(__i386__) || defined(__x86_64__))
00026
00027 # define SGATOMIC_USE_GCC4_BUILTINS
00028 #elif defined(__sgi) && defined(_COMPILER_VERSION) && (_COMPILER_VERSION>=730)
00029
00030 # define SGATOMIC_USE_MIPSPRO_BUILTINS
00031 #elif defined(_WIN32)
00032 # include <windows.h>
00033 # define SGATOMIC_USE_WIN32_INTERLOCKED
00034 #else
00035
00036 # include <simgear/threads/SGThread.hxx>
00037 # include <simgear/threads/SGGuard.hxx>
00038 #endif
00039
00040 class SGAtomic {
00041 public:
00042 SGAtomic(unsigned value = 0) : mValue(value)
00043 { }
00044 unsigned operator++()
00045 {
00046 #if defined(SGATOMIC_USE_GCC4_BUILTINS)
00047 return __sync_add_and_fetch(&mValue, 1);
00048 #elif defined(SGATOMIC_USE_MIPOSPRO_BUILTINS)
00049 return __add_and_fetch(&mValue, 1);
00050 #elif defined(SGATOMIC_USE_WIN32_INTERLOCKED)
00051 return InterlockedIncrement(reinterpret_cast<long volatile*>(&mValue));
00052 #else
00053 SGGuard<SGMutex> lock(mMutex);
00054 return ++mValue;
00055 #endif
00056 }
00057 unsigned operator--()
00058 {
00059 #if defined(SGATOMIC_USE_GCC4_BUILTINS)
00060 return __sync_sub_and_fetch(&mValue, 1);
00061 #elif defined(SGATOMIC_USE_MIPOSPRO_BUILTINS)
00062 return __sub_and_fetch(&mValue, 1);
00063 #elif defined(SGATOMIC_USE_WIN32_INTERLOCKED)
00064 return InterlockedDecrement(reinterpret_cast<long volatile*>(&mValue));
00065 #else
00066 SGGuard<SGMutex> lock(mMutex);
00067 return --mValue;
00068 #endif
00069 }
00070 operator unsigned() const
00071 {
00072 #if defined(SGATOMIC_USE_GCC4_BUILTINS)
00073 __sync_synchronize();
00074 return mValue;
00075 #elif defined(SGATOMIC_USE_MIPOSPRO_BUILTINS)
00076 __synchronize();
00077 return mValue;
00078 #elif defined(SGATOMIC_USE_WIN32_INTERLOCKED)
00079 return static_cast<unsigned const volatile &>(mValue);
00080 #else
00081 SGGuard<SGMutex> lock(mMutex);
00082 return mValue;
00083 #endif
00084 }
00085
00086 bool compareAndExchange(unsigned oldValue, unsigned newValue)
00087 {
00088 #if defined(SGATOMIC_USE_GCC4_BUILTINS)
00089 return __sync_bool_compare_and_swap(&mValue, oldValue, newValue);
00090 #elif defined(SGATOMIC_USE_MIPOSPRO_BUILTINS)
00091 return __compare_and_swap(&mValue, oldValue, newValue);
00092 #elif defined(SGATOMIC_USE_WIN32_INTERLOCKED)
00093 long volatile* lvPtr = reinterpret_cast<long volatile*>(&mValue);
00094 return oldValue == InterlockedCompareExchange(lvPtr, newValue, oldValue);
00095 #else
00096 SGGuard<SGMutex> lock(mMutex);
00097 if (mValue != oldValue)
00098 return false;
00099 mValue = newValue;
00100 return true;
00101 #endif
00102 }
00103
00104 private:
00105 SGAtomic(const SGAtomic&);
00106 SGAtomic& operator=(const SGAtomic&);
00107
00108 #if !defined(SGATOMIC_USE_GCC4_BUILTINS) \
00109 && !defined(SGATOMIC_USE_MIPOSPRO_BUILTINS) \
00110 && !defined(SGATOMIC_USE_WIN32_INTERLOCKED)
00111 mutable SGMutex mMutex;
00112 #endif
00113 unsigned mValue;
00114 };
00115
00116 namespace simgear
00117 {
00118
00119 template <typename T>
00120 class Swappable : private SGAtomic
00121 {
00122 public:
00123 Swappable(const T& value) : SGAtomic(static_cast<unsigned>(value))
00124 {
00125 }
00126 T operator() () const
00127 {
00128 return static_cast<T>(SGAtomic::operator unsigned ());
00129 }
00130 Swappable& operator=(const Swappable& rhs)
00131 {
00132 for (unsigned oldval = unsigned(*this);
00133 !compareAndExchange(oldval, unsigned(rhs));
00134 oldval = unsigned(*this))
00135 ;
00136 return *this;
00137 }
00138 bool compareAndSwap(const T& oldVal, const T& newVal)
00139 {
00140 return SGAtomic::compareAndExchange(static_cast<unsigned>(oldVal),
00141 static_cast<unsigned>(newVal));
00142 }
00143 };
00144 }
00145 #endif