00001
00024 #ifndef GALOIS_ATOMIC_H
00025 #define GALOIS_ATOMIC_H
00026
00027 #include "Galois/Runtime/ll/CacheLineStorage.h"
00028
00029 #include <iterator>
00030
00031 namespace Galois {
00032
00033 namespace AtomicImpl {
00037 template<typename T, template <typename _> class W>
00038 class GAtomicImpl {
00039
00040 W<T> val;
00041
00042 public:
00044 explicit GAtomicImpl(const T& i): val(i) {}
00046 GAtomicImpl() {}
00047
00049 T operator+=(const T& rhs) {
00050 return __sync_add_and_fetch(&val.data, rhs);
00051 }
00053 T operator-=(const T& rhs) {
00054 return __sync_sub_and_fetch(&(val.data), rhs);
00055 }
00057 T operator++() {
00058 return __sync_add_and_fetch(&(val.data), 1);
00059 }
00061 T operator++(int) {
00062 return __sync_fetch_and_add(&(val.data), 1);
00063 }
00065 T operator--() {
00066 return __sync_sub_and_fetch(&(val.data), 1);
00067 }
00069 T operator--(int) {
00070 return __sync_fetch_and_sub(&(val.data), 1);
00071 }
00073 operator T() const {
00074 return val.data;
00075 }
00077 T& operator=(const T& i) {
00078 return val.data = i;
00079 }
00081 T& operator=(const GAtomicImpl& i) {
00082 return val.data = i.val.data;
00083 }
00085 bool cas (const T& expected, const T& updated) {
00086 if (val.data != expected) { return false; }
00087 #if defined(__INTEL_COMPILER)
00088 return __sync_bool_compare_and_swap(
00089 &val.data,
00090 *reinterpret_cast<const ptrdiff_t*>(&expected),
00091 *reinterpret_cast<const ptrdiff_t*>(&updated));
00092 #else
00093 return __sync_bool_compare_and_swap (&val.data, expected, updated);
00094 #endif
00095 }
00096 };
00097
00099 template <typename T, template <typename _> class W>
00100 class GAtomicBase: public GAtomicImpl<T, W> {
00101 typedef GAtomicImpl<T, W> Super_ty;
00102
00103 public:
00105 explicit GAtomicBase(const T& i): Super_ty (i) {}
00106
00108 GAtomicBase(): Super_ty () {}
00109
00110 T& operator=(const GAtomicBase& that) {
00111 return Super_ty::operator=(that);
00112 }
00113
00114 T& operator=(const T& that) {
00115 return Super_ty::operator=(that);
00116 }
00117 };
00118
00120 template <typename T, template <typename _> class W>
00121 class GAtomicBase<T*, W>: public GAtomicImpl<T*, W> {
00122 typedef GAtomicImpl<T*, W> Super_ty;
00123
00124 public:
00125 typedef typename std::iterator_traits<T*>::difference_type difference_type;
00126
00127 GAtomicBase(): Super_ty() {}
00128
00129 GAtomicBase(T* i): Super_ty(i) {}
00130
00131 T*& operator=(const GAtomicBase& that) {
00132 return Super_ty::operator=(that);
00133 }
00134
00135 T*& operator=(T* that) {
00136 return Super_ty::operator=(that);
00137 }
00138
00139 T* operator+=(const difference_type& rhs) {
00140 return __sync_add_and_fetch(&Super_ty::val.data, rhs);
00141 }
00142
00143 T* operator-=(const difference_type& rhs) {
00144 return __sync_sub_and_fetch(&Super_ty::val.data, rhs);
00145 }
00146 };
00147
00149 template <typename T, template <typename _> class W>
00150 class GAtomicBase<const T*, W>: public GAtomicImpl<const T*, W> {
00151 typedef GAtomicImpl<const T*, W> Super_ty;
00152
00153 public:
00154 typedef typename std::iterator_traits<const T*>::difference_type difference_type;
00155
00156 GAtomicBase(): Super_ty() {}
00157
00158 GAtomicBase(const T* i): Super_ty(i) {}
00159
00160 const T*& operator=(const GAtomicBase& that) {
00161 return Super_ty::operator=(that);
00162 }
00163
00164 const T*& operator=(const T* that) {
00165 return Super_ty::operator=(that);
00166 }
00167
00168 const T* operator+=(const difference_type& rhs) {
00169 return __sync_add_and_fetch(&Super_ty::val.data, rhs);
00170 }
00171
00172 const T* operator-=(const difference_type& rhs) {
00173 return __sync_sub_and_fetch(&Super_ty::val.data, rhs);
00174 }
00175 };
00176
00178 template<template <typename _> class W>
00179 class GAtomicBase<bool, W>: private GAtomicImpl<bool, W> {
00180 typedef GAtomicImpl<bool, W> Super_ty;
00181
00182 public:
00184 explicit GAtomicBase(bool i): Super_ty(i) {}
00185
00186 GAtomicBase(): Super_ty() {}
00187
00189 operator bool() const {
00190 return Super_ty::operator bool ();
00191 }
00192
00194 bool& operator=(const GAtomicBase<bool, W>& i) {
00195 return Super_ty::operator=(i);
00196 }
00197
00199 bool& operator=(bool i) {
00200 return Super_ty::operator=(i);
00201 }
00203 bool cas(bool expected, bool updated) {
00204 return Super_ty::cas(expected, updated);
00205 }
00206 };
00207
00208
00209 template <typename T>
00210 struct DummyWrapper {
00211 T data;
00212
00213 explicit DummyWrapper(const T& d): data (d) {}
00214 DummyWrapper() {}
00215 };
00216
00217 }
00218
00224 template <typename T>
00225 class GAtomic: public AtomicImpl::GAtomicBase <T, AtomicImpl::DummyWrapper> {
00226 typedef AtomicImpl::GAtomicBase<T, AtomicImpl::DummyWrapper> Super_ty;
00227
00228 public:
00229 GAtomic(): Super_ty() {}
00230 explicit GAtomic(const T& v): Super_ty(v) {}
00231
00232 T& operator=(const GAtomic& that) {
00233 return Super_ty::operator=(that);
00234 }
00235
00236 T& operator=(const T& that) {
00237 return Super_ty::operator=(that);
00238 }
00239 };
00240
00244 template <typename T>
00245 class GAtomicPadded:
00246 public AtomicImpl::GAtomicBase<T, Galois::Runtime::LL::CacheLineStorage> {
00247
00248 typedef AtomicImpl::GAtomicBase<T, Galois::Runtime::LL::CacheLineStorage> Super_ty;
00249
00250 public:
00251 GAtomicPadded(): Super_ty () {}
00252 explicit GAtomicPadded(const T& v): Super_ty (v) {}
00253
00254 T& operator=(const GAtomicPadded& that) {
00255 return Super_ty::operator=(that);
00256 }
00257
00258 T& operator=(const T& that) {
00259 return Super_ty::operator=(that);
00260 }
00261 };
00262
00263 }
00264
00265 #endif