]> git.mxchange.org Git - simgear.git/blobdiff - simgear/structure/SGAtomic.hxx
Minor compiler version detection issue.
[simgear.git] / simgear / structure / SGAtomic.hxx
index 7bf8226f6f7b82870d5587ef252398dd796bc14c..081a4906cd8c1c4990bcea1707e484e6479a05f6 100644 (file)
@@ -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
 #ifndef SGAtomic_HXX
 #define SGAtomic_HXX
 
-#if defined(__GNUC__) && (4 <= __GNUC__) && (1 <= __GNUC_MINOR__) \
+#if defined(__GNUC__) && ((4 < __GNUC__)||(4 == __GNUC__ && 1 <= __GNUC_MINOR__)) \
   && (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 <windows.h>
 # 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<long volatile*>(&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<long volatile*>(&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<unsigned const volatile &>(mValue);
 #else
     SGGuard<SGMutex> 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<long volatile*>(&mValue);
+    return oldValue == InterlockedCompareExchange(lvPtr, newValue, oldValue);
+#else
+    SGGuard<SGMutex> 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 <typename T>
+class Swappable : private SGAtomic
+{
+public:
+    Swappable(const T& value) : SGAtomic(static_cast<unsigned>(value))
+    {
+    }
+    T operator() () const
+    {
+        return static_cast<T>(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<unsigned>(oldVal),
+                                           static_cast<unsigned>(newVal));
+    }
+};
+}
 #endif