summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2012-08-13 18:21:53 +0000
committerDavid Robillard <d@drobilla.net>2012-08-13 18:21:53 +0000
commit331cdd5eb4cacd5396e7e56dd826b320212674fd (patch)
treefc4badc5fbdbbee9302e1ee158330b10fb3c83c6
parentca660c8b407affd24802c43429b6341e76010660 (diff)
downloadraul-331cdd5eb4cacd5396e7e56dd826b320212674fd.tar.gz
raul-331cdd5eb4cacd5396e7e56dd826b320212674fd.tar.bz2
raul-331cdd5eb4cacd5396e7e56dd826b320212674fd.zip
Drop glib for atomics and use gcc/clang builtins.
git-svn-id: http://svn.drobilla.net/lad/trunk/raul@4681 a436a847-0d15-0410-975c-d299462d15a1
-rw-r--r--raul/AtomicInt.hpp118
-rw-r--r--raul/AtomicPtr.hpp61
-rw-r--r--test/atomic_test.cpp41
3 files changed, 87 insertions, 133 deletions
diff --git a/raul/AtomicInt.hpp b/raul/AtomicInt.hpp
index 224b0dd..2fd624c 100644
--- a/raul/AtomicInt.hpp
+++ b/raul/AtomicInt.hpp
@@ -17,9 +17,9 @@
#ifndef RAUL_ATOMIC_INT_HPP
#define RAUL_ATOMIC_INT_HPP
-#ifdef RAUL_CPP0x
+#include "raul/barrier.hpp"
-#include <atomic>
+namespace Raul {
/** Atomic integer.
* \ingroup raul
@@ -30,118 +30,62 @@ public:
inline AtomicInt(const AtomicInt& copy) : _val(copy.get()) {}
- inline int get() const { return _val.load(); }
-
- inline void operator=(int val) { _val = val; }
- inline void operator=(const AtomicInt& val) { _val = val.get(); }
-
- inline void operator+=(int val) { _val += val; }
+ inline int get() const {
+ Raul::barrier();
+ return _val;
+ }
- inline void operator-=(int val) { _val -= val; }
+ inline void operator=(int val) {
+ _val = val;
+ Raul::barrier();
+ }
- inline bool operator==(int val) const { return _val == val; }
+ inline void operator=(const AtomicInt& val) {
+ _val = val.get();
+ Raul::barrier();
+ }
- inline int operator+(int val) const { return _val + val; }
+ inline AtomicInt& operator++() { return operator+=(1); }
+ inline AtomicInt& operator--() { return operator-=(1); }
+ inline bool operator==(int val) const { return get() == val; }
+ inline int operator+(int val) const { return get() + val; }
+ inline int operator-(int val) const { return get() - val; }
- inline AtomicInt& operator++() { ++_val; return *this; }
+ inline AtomicInt& operator+=(int val) {
+ __sync_fetch_and_add(&_val, val);
+ return *this;
+ }
- inline AtomicInt& operator--() { --_val; return *this; }
+ inline AtomicInt& operator-=(int val) {
+ __sync_fetch_and_sub(&_val, val);
+ return *this;
+ }
/** Set value to @a val iff current value is @a old.
* @return true iff set succeeded.
*/
inline bool compare_and_exchange(int old, int val) {
- return _val.compare_exchange_strong(old, val);
+ return __sync_bool_compare_and_swap(&_val, old, val);
}
/** Add val to value.
* @return value immediately before addition took place.
*/
inline int exchange_and_add(int val) {
- return _val.fetch_add(val);
+ return __sync_fetch_and_add(&_val, val);
}
/** Decrement value.
* @return true if value is now 0, otherwise false.
*/
inline bool decrement_and_test() {
- return _val.fetch_add(-1) == 0;
+ return __sync_sub_and_fetch(&_val, 1) == 0;
}
private:
- std::atomic<int> _val;
-};
-
-#else // !RAUL_CPP0x
-
-#include <glib.h>
-
-namespace Raul {
-
-/** Atomic integer.
- * \ingroup raul
- */
-class AtomicInt {
-public:
- inline AtomicInt(int val)
- { g_atomic_int_set(static_cast<volatile gint*>(&_val), val); }
-
- inline AtomicInt(const AtomicInt& copy)
- { g_atomic_int_set(static_cast<volatile gint*>(&_val), copy.get()); }
-
- inline int get() const
- { return g_atomic_int_get(static_cast<volatile gint*>(&_val)); }
-
- inline void operator=(int val)
- { g_atomic_int_set(static_cast<volatile gint*>(&_val), val); }
-
- inline void operator+=(int val)
- { g_atomic_int_add(static_cast<volatile gint*>(&_val), val); }
-
- inline void operator-=(int val)
- { g_atomic_int_add(static_cast<volatile gint*>(&_val), -val); }
-
- inline bool operator==(int val) const
- { return get() == val; }
-
- inline int operator+(int val) const
- { return get() + val; }
-
- inline AtomicInt& operator++() // prefix
- { g_atomic_int_inc(static_cast<volatile gint*>(&_val)); return *this; }
-
- inline AtomicInt& operator--() // prefix
- { g_atomic_int_add(static_cast<volatile gint*>(&_val), -1); return *this; }
-
- /** Set value to @a val iff current value is @a old.
- * @return true iff set succeeded.
- */
- inline bool compare_and_exchange(int old, int val)
- { return g_atomic_int_compare_and_exchange(static_cast<volatile gint*>(&_val), old, val); }
-
- /** Add val to value.
- * @return value immediately before addition took place.
- */
- inline int exchange_and_add(int val) {
-#if GLIB_CHECK_VERSION(2, 30, 0)
- return g_atomic_int_add(static_cast<volatile gint*>(&_val), val);
-#else
- return g_atomic_int_exchange_and_add(static_cast<volatile gint*>(&_val), val);
-#endif
- }
-
- /** Decrement value.
- * @return true if value is now 0, otherwise false.
- */
- inline bool decrement_and_test()
- { return g_atomic_int_dec_and_test(static_cast<volatile gint*>(&_val)); }
-
-private:
- volatile mutable int _val;
+ int _val;
};
} // namespace Raul
-#endif // RAUL_CPP0x
-
#endif // RAUL_ATOMIC_INT_HPP
diff --git a/raul/AtomicPtr.hpp b/raul/AtomicPtr.hpp
index 00337b4..91c5c35 100644
--- a/raul/AtomicPtr.hpp
+++ b/raul/AtomicPtr.hpp
@@ -19,9 +19,7 @@
#include <cstddef>
-#ifdef RAUL_CPP0x
-
-#include <atomic>
+#include "raul/barrier.hpp"
namespace Raul {
@@ -35,56 +33,27 @@ public:
inline AtomicPtr(const AtomicPtr& copy) : _val(copy.get()) {}
- inline T* get() const { return static_cast<T*>(_val.load()); }
-
- inline void operator=(T* val) { _val = val; }
-
- /** Set value to newval iff current value is oldval */
- inline bool compare_and_exchange(void* oldval, void* newval) {
- return _val.compare_exchange_strong(oldval, newval);
+ inline T* get() const {
+ Raul::barrier();
+ return static_cast<T*>(_val);
}
-private:
- std::atomic<void*> _val;
-};
-
-} // namespace Raul
-
-#else // !RAUL_CPP0x
-
-#include <glib.h>
-
-namespace Raul {
-
-/** Atomic pointer.
- * \ingroup raul
- */
-template<typename T>
-class AtomicPtr {
-public:
- inline AtomicPtr()
- { g_atomic_pointer_set(static_cast<volatile gpointer*>(&_val), NULL); }
-
- inline AtomicPtr(const AtomicPtr& copy)
- { g_atomic_pointer_set(static_cast<volatile gpointer*>(&_val),
- static_cast<gpointer>(copy.get())); }
-
- inline T* get() const
- { return static_cast<T*>(g_atomic_pointer_get(static_cast<volatile gpointer*>(&_val))); }
-
- inline void operator=(T* val)
- { g_atomic_pointer_set(&_val, static_cast<gpointer>(val)); }
+ inline void operator=(T* val) {
+ _val = val;
+ Raul::barrier();
+ }
- /** Set value to newval iff current value is oldval */
- inline bool compare_and_exchange(gpointer oldval, gpointer newval)
- { return g_atomic_pointer_compare_and_exchange(&_val, oldval, newval); }
+ /** Set value to @a val iff current value is @a old.
+ * @return true iff set succeeded.
+ */
+ inline bool compare_and_exchange(void* old, void* val) {
+ return __sync_bool_compare_and_swap(&_val, old, val);
+ }
private:
- mutable volatile gpointer _val;
+ void* _val;
};
} // namespace Raul
-#endif // RAUL_CPP0x
-
#endif // RAUL_ATOMIC_PTR_HPP
diff --git a/test/atomic_test.cpp b/test/atomic_test.cpp
index 51d710d..e3a8d73 100644
--- a/test/atomic_test.cpp
+++ b/test/atomic_test.cpp
@@ -20,10 +20,51 @@
using namespace std;
using namespace Raul;
+#define TEST(cond) { if (!(cond)) return 1; }
+
int
main()
{
/* TODO: Actually test functionality... */
+ AtomicInt i(0);
+ TEST(i == 0);
+
+ ++i;
+ TEST(i == 1);
+
+ --i;
+ TEST(i == 0);
+
+ TEST(i + 1 == 1);
+ TEST(i - 1 == -1);
+
+ i += 2;
+ TEST(i == 2);
+
+ i -= 4;
+ TEST(i == -2);
+
+ TEST(i.compare_and_exchange(-2, 0));
+ TEST(i == 0);
+
+ TEST(i.exchange_and_add(5) == 0);
+ TEST(i == 5);
+
+ i = 1;
+ TEST(i == 1);
+ TEST(i.decrement_and_test());
+
+ int five = 5;
+ int seven = 7;
+ AtomicPtr<int> p;
+ TEST(p.get() == NULL);
+
+ p = &five;
+ TEST(p.get() == &five);
+ TEST(*p.get() == 5);
+ TEST(p.compare_and_exchange(&five, &seven));
+ TEST(p.get() == &seven);
+ TEST(*p.get() = 7);
return 0;
}