Galois
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Atomic.h
Go to the documentation of this file.
1 /*
2  * This file belongs to the Galois project, a C++ library for exploiting
3  * parallelism. The code is being released under the terms of the 3-Clause BSD
4  * License (a copy is located in LICENSE.txt at the top-level directory).
5  *
6  * Copyright (C) 2018, The University of Texas at Austin. All rights reserved.
7  * UNIVERSITY EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES CONCERNING THIS
8  * SOFTWARE AND DOCUMENTATION, INCLUDING ANY WARRANTIES OF MERCHANTABILITY,
9  * FITNESS FOR ANY PARTICULAR PURPOSE, NON-INFRINGEMENT AND WARRANTIES OF
10  * PERFORMANCE, AND ANY WARRANTY THAT MIGHT OTHERWISE ARISE FROM COURSE OF
11  * DEALING OR USAGE OF TRADE. NO WARRANTY IS EITHER EXPRESS OR IMPLIED WITH
12  * RESPECT TO THE USE OF THE SOFTWARE OR DOCUMENTATION. Under no circumstances
13  * shall University be liable for incidental, special, indirect, direct or
14  * consequential damages or loss of profits, interruption of business, or
15  * related expenses which may arise from use of Software or Documentation,
16  * including but not limited to those resulting from defects in Software and/or
17  * Documentation, or loss or inaccuracy of data of any kind.
18  */
19 
20 #ifndef GALOIS_ATOMIC_H
21 #define GALOIS_ATOMIC_H
22 
23 #include <iterator>
24 
25 #include "galois/config.h"
27 
28 namespace galois {
29 
30 namespace internal {
34 template <typename T, template <typename _> class W, bool CONCURRENT>
35 class GAtomicImpl {
36  // galois::runtime::LL::CacheLineStorage<T> val;
37  W<T> val;
38 
39 public:
41  explicit GAtomicImpl(const T& i) : val(i) {}
43  GAtomicImpl() {}
44 
46  T operator+=(const T& rhs) { return __sync_add_and_fetch(&val.data, rhs); }
48  T operator-=(const T& rhs) { return __sync_sub_and_fetch(&(val.data), rhs); }
50  T operator++() { return __sync_add_and_fetch(&(val.data), 1); }
52  T operator++(int) { return __sync_fetch_and_add(&(val.data), 1); }
54  T operator--() { return __sync_sub_and_fetch(&(val.data), 1); }
56  T operator--(int) { return __sync_fetch_and_sub(&(val.data), 1); }
58  operator T() const { return val.data; }
60  T& operator=(const T& i) { return val.data = i; }
62  T& operator=(const GAtomicImpl& i) { return val.data = i.val.data; }
64  bool cas(const T& expected, const T& updated) {
65  if (val.data != expected) {
66  return false;
67  }
68 #if defined(__INTEL_COMPILER)
69  return __sync_bool_compare_and_swap(
70  &val.data, *reinterpret_cast<const ptrdiff_t*>(&expected),
71  *reinterpret_cast<const ptrdiff_t*>(&updated));
72 #else
73  return __sync_bool_compare_and_swap(&val.data, expected, updated);
74 #endif
75  }
76 };
77 
78 // non-current version
79 template <typename T, template <typename _> class W>
80 class GAtomicImpl<T, W, false> {
81  // galois::runtime::LL::CacheLineStorage<T> val;
82  W<T> val;
83 
84 public:
86  explicit GAtomicImpl(const T& i) : val(i) {}
88  GAtomicImpl() {}
89 
91  T operator+=(const T& rhs) { return (val.data += rhs); }
93  T operator-=(const T& rhs) { return (val.data -= rhs); }
95  T operator++() { return ++(val.data); }
97  T operator++(int) { return (val.data)++; }
99  T operator--() { return --(val.data); }
101  T operator--(int) { return (val.data)--; }
103  operator T() const { return val.data; }
105  T& operator=(const T& i) { return val.data = i; }
107  T& operator=(const GAtomicImpl& i) { return val.data = i.val.data; }
109  bool cas(const T& expected, const T& updated) {
110  if (val.data != expected) {
111  return false;
112  } else {
113  val.data = updated;
114  return true;
115  }
116  }
117 };
118 
120 template <typename T, template <typename _> class W, bool CONCURRENT>
121 class GAtomicBase : public GAtomicImpl<T, W, CONCURRENT> {
122  typedef GAtomicImpl<T, W, CONCURRENT> Super_ty;
123 
124 public:
126  explicit GAtomicBase(const T& i) : Super_ty(i) {}
127 
129  GAtomicBase() : Super_ty() {}
130 
131  T& operator=(const GAtomicBase& that) { return Super_ty::operator=(that); }
132 
133  T& operator=(const T& that) { return Super_ty::operator=(that); }
134 };
135 
137 template <typename T, template <typename _> class W, bool CONCURRENT>
138 class GAtomicBase<T*, W, CONCURRENT> : public GAtomicImpl<T*, W, CONCURRENT> {
139  typedef GAtomicImpl<T*, W, CONCURRENT> Super_ty;
140 
141 public:
142  typedef typename std::iterator_traits<T*>::difference_type difference_type;
143 
144  GAtomicBase() : Super_ty() {}
145 
146  GAtomicBase(T* i) : Super_ty(i) {}
147 
148  T*& operator=(const GAtomicBase& that) { return Super_ty::operator=(that); }
149 
150  T*& operator=(T* that) { return Super_ty::operator=(that); }
151 
152  T* operator+=(const difference_type& rhs) {
153  if (CONCURRENT) {
154  return __sync_add_and_fetch(&Super_ty::val.data, rhs);
155  } else {
156  return (Super_ty::val.data += rhs);
157  }
158  }
159 
160  T* operator-=(const difference_type& rhs) {
161  if (CONCURRENT) {
162  return __sync_sub_and_fetch(&Super_ty::val.data, rhs);
163  } else {
164  return (Super_ty::val.data -= rhs);
165  }
166  }
167 };
168 
170 template <typename T, template <typename _> class W, bool CONCURRENT>
171 class GAtomicBase<const T*, W, CONCURRENT>
172  : public GAtomicImpl<const T*, W, CONCURRENT> {
173  typedef GAtomicImpl<const T*, W, CONCURRENT> Super_ty;
174 
175 public:
176  typedef
177  typename std::iterator_traits<const T*>::difference_type difference_type;
178 
179  GAtomicBase() : Super_ty() {}
180 
181  GAtomicBase(const T* i) : Super_ty(i) {}
182 
183  const T*& operator=(const GAtomicBase& that) {
184  return Super_ty::operator=(that);
185  }
186 
187  const T*& operator=(const T* that) { return Super_ty::operator=(that); }
188 
189  const T* operator+=(const difference_type& rhs) {
190  if (CONCURRENT) {
191  return __sync_add_and_fetch(&Super_ty::val.data, rhs);
192  } else {
193  return (Super_ty::val.data += rhs);
194  }
195  }
196 
197  const T* operator-=(const difference_type& rhs) {
198  if (CONCURRENT) {
199  return __sync_sub_and_fetch(&Super_ty::val.data, rhs);
200  } else {
201  return (Super_ty::val.data -= rhs);
202  }
203  }
204 };
205 
207 template <template <typename _> class W, bool CONCURRENT>
208 class GAtomicBase<bool, W, CONCURRENT>
209  : private GAtomicImpl<bool, W, CONCURRENT> {
210  typedef GAtomicImpl<bool, W, CONCURRENT> Super_ty;
211 
212 public:
214  explicit GAtomicBase(bool i) : Super_ty(i) {}
215 
216  GAtomicBase() : Super_ty() {}
217 
219  operator bool() const { return Super_ty::operator bool(); }
220 
222  bool& operator=(const GAtomicBase& i) { return Super_ty::operator=(i); }
223 
225  bool& operator=(bool i) { return Super_ty::operator=(i); }
227  bool cas(bool expected, bool updated) {
228  return Super_ty::cas(expected, updated);
229  }
230 };
231 
232 template <typename T>
233 struct DummyWrapper {
234  T data;
235 
236  explicit DummyWrapper(const T& d) : data(d) {}
237  DummyWrapper() {}
238 };
239 
240 } // namespace internal
241 
247 template <typename T, bool CONCURRENT = true>
248 class GAtomic
249  : public internal::GAtomicBase<T, internal::DummyWrapper, CONCURRENT> {
250  typedef internal::GAtomicBase<T, internal::DummyWrapper, CONCURRENT> Super_ty;
251 
252 public:
253  GAtomic() : Super_ty() {}
254  explicit GAtomic(const T& v) : Super_ty(v) {}
255 
256  T& operator=(const GAtomic& that) { return Super_ty::operator=(that); }
257 
258  T& operator=(const T& that) { return Super_ty::operator=(that); }
259 };
260 
264 template <typename T, bool CONCURRENT = true>
266  : public internal::GAtomicBase<T, galois::substrate::CacheLineStorage,
267  CONCURRENT> {
268 
269  typedef internal::GAtomicBase<T, galois::substrate::CacheLineStorage,
270  CONCURRENT>
271  Super_ty;
272 
273 public:
274  GAtomicPadded() : Super_ty() {}
275  explicit GAtomicPadded(const T& v) : Super_ty(v) {}
276 
277  T& operator=(const GAtomicPadded& that) { return Super_ty::operator=(that); }
278 
279  T& operator=(const T& that) { return Super_ty::operator=(that); }
280 };
281 
282 } // namespace galois
283 
284 #endif
T & operator=(const GAtomic &that)
Definition: Atomic.h:256
Definition: CacheLineStorage.h:32
Cache-line padded version of GAtomic.
Definition: Atomic.h:265
GAtomic()
Definition: Atomic.h:253
T & operator=(const T &that)
Definition: Atomic.h:258
T & operator=(const T &that)
Definition: Atomic.h:279
T & operator=(const GAtomicPadded &that)
Definition: Atomic.h:277
GAtomicPadded()
Definition: Atomic.h:274
GAtomic(const T &v)
Definition: Atomic.h:254
GAtomicPadded(const T &v)
Definition: Atomic.h:275
An atomic wrapper that provides sensible atomic behavior for most primative data types.
Definition: Atomic.h:248