/* -*-c++-*-
*
- * Copyright (C) 2005-2006 Mathias Froehlich
+ * Copyright (C) 2005-2009,2011 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__) \
- && (defined(__i386__) || defined(__x86_64__))
+#if defined(__GNUC__) && ((4 < __GNUC__)||(4 == __GNUC__ && 1 <= __GNUC_MINOR__)) && \
+ defined(__x86_64__)
// No need to include something. Is a Compiler API ...
# define SGATOMIC_USE_GCC4_BUILTINS
-#elif defined(WIN32)
-# include <windows.h>
-# define SGATOMIC_USE_WIN32_INTERLOCKED
+#elif defined(__GNUC__) && defined(__i386__)
+# define SGATOMIC_USE_LIBRARY_FUNCTIONS
+#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)
+# define SGATOMIC_USE_LIBRARY_FUNCTIONS
#else
// The sledge hammer ...
+# define SGATOMIC_USE_LIBRARY_FUNCTIONS
+# define SGATOMIC_USE_MUTEX
# include <simgear/threads/SGThread.hxx>
-# include <simgear/threads/SGGuard.hxx>
#endif
class SGAtomic {
public:
SGAtomic(unsigned value = 0) : mValue(value)
{ }
+
+#if defined(SGATOMIC_USE_LIBRARY_FUNCTIONS)
+ unsigned operator++();
+#else
unsigned operator++()
{
-#if defined(SGATOMIC_USE_GCC4_BUILTINS)
+# if defined(SGATOMIC_USE_GCC4_BUILTINS)
return __sync_add_and_fetch(&mValue, 1);
-#elif defined(SGATOMIC_USE_WIN32_INTERLOCKED)
- return InterlockedIncrement(reinterpret_cast<long volatile*>(&mValue));
-#else
- SGGuard<SGMutex> lock(mMutex);
- return ++mValue;
-#endif
+# elif defined(SGATOMIC_USE_MIPOSPRO_BUILTINS)
+ return __add_and_fetch(&mValue, 1);
+# else
+# error
+# endif
}
+#endif
+
+#if defined(SGATOMIC_USE_LIBRARY_FUNCTIONS)
+ unsigned operator--();
+#else
unsigned operator--()
{
-#if defined(SGATOMIC_USE_GCC4_BUILTINS)
+# if defined(SGATOMIC_USE_GCC4_BUILTINS)
return __sync_sub_and_fetch(&mValue, 1);
-#elif defined(SGATOMIC_USE_WIN32_INTERLOCKED)
- return InterlockedDecrement(reinterpret_cast<long volatile*>(&mValue));
-#else
- SGGuard<SGMutex> lock(mMutex);
- return --mValue;
-#endif
+# elif defined(SGATOMIC_USE_MIPOSPRO_BUILTINS)
+ return __sub_and_fetch(&mValue, 1);
+# else
+# error
+# endif
}
+#endif
+
+#if defined(SGATOMIC_USE_LIBRARY_FUNCTIONS)
+ operator unsigned() const;
+#else
operator unsigned() const
{
-#if defined(SGATOMIC_USE_GCC4_BUILTINS)
+# if defined(SGATOMIC_USE_GCC4_BUILTINS)
__sync_synchronize();
return mValue;
-#elif defined(SGATOMIC_USE_WIN32_INTERLOCKED)
- return static_cast<unsigned const volatile &>(mValue);
-#else
- SGGuard<SGMutex> lock(mMutex);
+# elif defined(SGATOMIC_USE_MIPOSPRO_BUILTINS)
+ __synchronize();
return mValue;
+# else
+# error
+# endif
+ }
+#endif
+
+#if defined(SGATOMIC_USE_LIBRARY_FUNCTIONS)
+ bool compareAndExchange(unsigned oldValue, unsigned newValue);
+#else
+ 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);
+# else
+# error
+# endif
+ }
#endif
- }
private:
SGAtomic(const SGAtomic&);
SGAtomic& operator=(const SGAtomic&);
-#if !defined(SGATOMIC_USE_GCC4_BUILTINS) \
- && !defined(SGATOMIC_USE_WIN32_INTERLOCKED)
+#if defined(SGATOMIC_USE_MUTEX)
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