/* -*-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
#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) && !defined ( __CYGWIN__ )
+#elif defined(_WIN32)
# include <windows.h>
# define SGATOMIC_USE_WIN32_INTERLOCKED
#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&);
&& !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