DASH  0.3.0
GlobAtomicRef.h
1 #ifndef DASH__ATOMIC_GLOBREF_H_
2 #define DASH__ATOMIC_GLOBREF_H_
3 
4 #include <dash/GlobPtr.h>
5 //#include <dash/Types.h>
6 #include <dash/algorithm/Operation.h>
7 #include <dash/iterator/internal/GlobRefBase.h>
8 
9 namespace dash {
10 
11 // forward decls
12 template <typename T>
13 class Atomic;
14 
15 
16 template <typename T>
22 template <typename T>
23 class GlobRef<dash::Atomic<T>> {
24  /* Notes on type compatibility:
25  *
26  * - The general support of atomic operations on values of type T is
27  * checked in `dash::Atomic` and is not verified here.
28  * - Whether arithmetic operations (like `fetch_add`) are supported
29  * for values of type T is implicitly tested in the DASH operation
30  * types (like `dash::plus<T>`) and is not verified here.
31  *
32  */
33 
34  template <typename U>
35  friend std::ostream& operator<<(std::ostream& os, const GlobRef<U>& gref);
36 
37 public:
38  using value_type = T;
39  using const_value_type = typename std::add_const<T>::type;
40  using nonconst_value_type = typename std::remove_const<T>::type;
41  using atomic_t = dash::Atomic<T>;
42  using const_atomic_t = typename dash::Atomic<const_value_type>;
43  using nonconst_atomic_t = typename dash::Atomic<nonconst_value_type>;
44  using self_t = GlobRef<atomic_t>;
47 
48 private:
49  dart_gptr_t _gptr{};
50 
51 
52 public:
56  GlobRef() = delete;
57 
58  //TODO rkowalewski: Clarify constructors by passing various pointer types
59 
63  explicit GlobRef(dart_gptr_t dart_gptr)
64  : _gptr(dart_gptr)
65  {
66  DASH_LOG_TRACE_VAR("GlobRef(dart_gptr_t)", dart_gptr);
67  }
68 
73  template <typename PatternT>
74  explicit GlobRef(
77  : GlobRef(gptr.dart_gptr())
78  {
79  static_assert(
80  std::is_same<value_type, const_value_type>::value,
81  "Cannot create GlobRef<Atomic<T>> from GlobPtr<Atomic<const T>>!");
82  }
83 
84  template <typename PatternT>
85  explicit GlobRef(
88  : GlobRef(gptr.dart_gptr())
89  {
90  }
91 
100  template <
101  typename _T,
102  int = internal::enable_implicit_copy_ctor<value_type, _T>::value>
104  : GlobRef(gref.dart_gptr())
105  {
106  }
107 
114  template <
115  typename _T,
116  long = internal::enable_explicit_copy_ctor<value_type, _T>::value>
117  explicit GlobRef(const GlobRef<dash::Atomic<_T>>& gref)
118  : GlobRef(gref.dart_gptr())
119  {
120  }
121 
130  template <
131  typename _T,
132  int = internal::enable_implicit_copy_ctor<value_type, _T>::value>
134  : GlobRef(gref.dart_gptr())
135  {
136  }
137 
144  template <
145  typename _T,
146  long = internal::enable_explicit_copy_ctor<value_type, _T>::value>
147  explicit GlobRef(const GlobAsyncRef<dash::Atomic<_T>>& gref)
148  : GlobRef(gref.dart_gptr())
149  {
150  }
151 
155  GlobRef(self_t&& other) = default;
156 
160  self_t& operator=(const self_t& other) const
161  {
162  store(static_cast<atomic_t>(other));
163  return *this;
164  }
165 
169  self_t& operator=(self_t&& other) {
170  operator=(other);
171  return *this;
172  }
173 
174  operator T() const
175  {
176  return load();
177  }
178 
179  dart_gptr_t dart_gptr() const
180  {
181  return _gptr;
182  }
183 
188  bool is_local() const
189  {
190  return dash::internal::is_local(_gptr);
191  }
192 
203  T operator=(const T& value) const
204  {
205  store(value);
206  return value;
207  }
208 
212  void set(const T& value) const
213  {
214  static_assert(
215  dash::dart_punned_datatype<T>::value != DART_TYPE_UNDEFINED,
216  "Basic type or type smaller than 64bit required for "
217  "atomic set!");
218  static_assert(
219  std::is_same<value_type, nonconst_value_type>::value,
220  "Cannot modify value referenced by GlobRef<Atomic<const T>>!");
221  DASH_LOG_DEBUG_VAR("GlobRef<Atomic>.store()", value);
222  DASH_LOG_TRACE_VAR("GlobRef<Atomic>.store", _gptr);
224  _gptr,
225  &value,
226  1,
229  dart_flush(_gptr);
230  DASH_ASSERT_EQ(DART_OK, ret, "dart_accumulate failed");
231  DASH_LOG_DEBUG("GlobRef<Atomic>.store >");
232  }
233 
237  inline void store(const T& value) const
238  {
239  set(value);
240  }
241 
243  T get() const
244  {
245  static_assert(
246  dash::dart_punned_datatype<T>::value != DART_TYPE_UNDEFINED,
247  "Basic type or type smaller than 64bit required for "
248  "atomic get!");
249  DASH_LOG_DEBUG("GlobRef<Atomic>.load()");
250  DASH_LOG_TRACE_VAR("GlobRef<Atomic>.load", _gptr);
251  nonconst_value_type nothing;
252  nonconst_value_type result;
254  _gptr,
255  &nothing,
256  &result,
258  DART_OP_NO_OP);
259  dart_flush_local(_gptr);
260  DASH_ASSERT_EQ(DART_OK, ret, "dart_accumulate failed");
261  DASH_LOG_DEBUG_VAR("GlobRef<Atomic>.get >", result);
262  return result;
263  }
264 
268  inline T load() const
269  {
270  return get();
271  }
272 
276  template <typename BinaryOp>
277  void op(
279  BinaryOp binary_op,
281  const T& value) const
282  {
283  static_assert(
284  dash::dart_punned_datatype<T>::value != DART_TYPE_UNDEFINED,
285  "Basic type or type smaller than 64bit required for "
286  "atomic operation!");
287  static_assert(
288  dash::dart_datatype<T>::value != DART_TYPE_UNDEFINED ||
289  binary_op.op_kind() != dash::internal::OpKind::ARITHMETIC,
290  "Atomic arithmetic operations only valid on basic types");
291  static_assert(
292  std::is_same<value_type, nonconst_value_type>::value,
293  "Cannot modify value referenced by GlobRef<Atomic<const T>>!");
294  DASH_LOG_DEBUG_VAR("GlobRef<Atomic>.op()", value);
295  DASH_LOG_TRACE_VAR("GlobRef<Atomic>.op", _gptr);
296  nonconst_value_type acc = value;
297  DASH_LOG_TRACE("GlobRef<Atomic>.op", "dart_accumulate");
299  _gptr,
300  &acc,
301  1,
303  binary_op.dart_operation());
304  dart_flush(_gptr);
305  DASH_ASSERT_EQ(DART_OK, ret, "dart_accumulate failed");
306  DASH_LOG_DEBUG_VAR("GlobRef<Atomic>.op >", acc);
307  }
308 
315  template <typename BinaryOp>
317  BinaryOp binary_op,
319  const T& value) const
320  {
321  static_assert(
322  dash::dart_punned_datatype<T>::value != DART_TYPE_UNDEFINED,
323  "Basic type or type smaller than 64bit required for "
324  "atomic fetch_op!");
325  static_assert(
326  dash::dart_datatype<T>::value != DART_TYPE_UNDEFINED ||
327  binary_op.op_kind() != dash::internal::OpKind::ARITHMETIC,
328  "Atomic arithmetic operations only valid on basic types!");
329  static_assert(
330  std::is_same<value_type, nonconst_value_type>::value,
331  "Cannot modify value referenced by GlobRef<Atomic<const T>>!");
332  DASH_LOG_DEBUG_VAR("GlobRef<Atomic>.fetch_op()", value);
333  DASH_LOG_TRACE_VAR("GlobRef<Atomic>.fetch_op", _gptr);
334  DASH_LOG_TRACE_VAR("GlobRef<Atomic>.fetch_op", typeid(value).name());
335  nonconst_value_type res;
337  _gptr,
338  &value,
339  &res,
341  binary_op.dart_operation());
342  dart_flush(_gptr);
343  DASH_ASSERT_EQ(DART_OK, ret, "dart_fetch_op failed");
344  DASH_LOG_DEBUG_VAR("GlobRef<Atomic>.fetch_op >", res);
345  return res;
346  }
347 
351  T exchange(const T& value) const
352  {
353  return fetch_op(dash::second<T>(), value);
354  }
355 
364  bool compare_exchange(const T& expected, const T& desired) const
365  {
366  static_assert(
367  dash::dart_punned_datatype<T>::value != DART_TYPE_UNDEFINED,
368  "Integral type or type smaller than 64bit required for "
369  "compare_exchange!");
370  static_assert(
371  !std::is_floating_point<T>::value,
372  "compare_exchange not available for floating point!");
373  static_assert(
374  std::is_same<value_type, nonconst_value_type>::value,
375  "Cannot modify value referenced by GlobRef<const T>!");
376  DASH_LOG_DEBUG_VAR("GlobRef<Atomic>.compare_exchange()", desired);
377  DASH_LOG_TRACE_VAR("GlobRef<Atomic>.compare_exchange", _gptr);
378  DASH_LOG_TRACE_VAR("GlobRef<Atomic>.compare_exchange", expected);
379  DASH_LOG_TRACE_VAR(
380  "GlobRef<Atomic>.compare_exchange", typeid(desired).name());
381  nonconst_value_type result;
383  _gptr,
384  &desired,
385  &expected,
386  &result,
388  dart_flush(_gptr);
389  DASH_ASSERT_EQ(DART_OK, ret, "dart_compare_and_swap failed");
390  DASH_LOG_DEBUG_VAR(
391  "GlobRef<Atomic>.compare_exchange >", (expected == result));
392  return (expected == result);
393  }
394 
399  void add(const T& value) const
400  {
401  static_assert(
402  std::is_same<value_type, nonconst_value_type>::value,
403  "Cannot modify value referenced by GlobRef<const T>!");
404  op(dash::plus<T>(), value);
405  }
406 
415  const T& value) const
416  {
417  return fetch_op(dash::plus<T>(), value);
418  }
419 
424  void sub(const T& value) const
425  {
426  op(dash::plus<T>(), -value);
427  }
428 
437  const T& value) const
438  {
439  return fetch_op(dash::plus<T>(), -value);
440  }
441 
446  void multiply(const T& value) const
447  {
448  op(dash::multiply<T>(), value);
449  }
450 
459  const T& value) const
460  {
461  return fetch_op(dash::multiply<T>(), value);
462  }
463 
475  T operator++() const
476  {
477  return fetch_add(1) + 1;
478  }
479 
486  T operator++(int) const
487  {
488  return fetch_add(1);
489  }
490 
502  T operator--() const
503  {
504  return fetch_sub(1) - 1;
505  }
506 
513  T operator--(int) const
514  {
515  return fetch_sub(1);
516  }
517 
529  T operator+=(const T& value) const
530  {
531  return fetch_add(value) + value;
532  }
533 
545  T operator-=(const T& value) const
546  {
547  return fetch_sub(value) - value;
548  }
549 };
550 
551 } // namespace dash
552 
553 #endif // DASH__ATOMIC_GLOBREF_H_
void store(const T &value) const
Set the value of the shared atomic variable.
Returns second operand.
Definition: Operation.h:218
Reduce operands to their sum.
Definition: Operation.h:163
GlobRef()=delete
Reference semantics forbid declaration without definition.
This class is a simple memory pool which holds allocates elements of size ValueType.
Definition: AllOf.h:8
void multiply(const T &value) const
DASH specific variant which is faster than fetch_multiply but does not return value.
self_t & operator=(self_t &&other)
Move Assignment: Redirects to Copy Assignment.
Signals success.
Definition: dart_types.h:33
GlobRef(const GlobPtr< nonconst_atomic_t, PatternT > &gptr)
Definition: GlobAtomicRef.h:85
No operation.
Definition: dart_types.h:97
dart_ret_t dart_flush_local(dart_gptr_t gptr)
Guarantee local completion of all outstanding operations involving a segment on a certain unit...
Type wrapper to mark any trivial type atomic.
dart_ret_t dart_accumulate(dart_gptr_t gptr, const void *values, size_t nelem, dart_datatype_t dtype, dart_operation_t op)
Perform an element-wise atomic update on the values pointed to by gptr by applying the operation op w...
T load() const
Get the value of the shared atomic variable.
Type trait for mapping to punned DART data type for reduce operations.
Definition: Types.h:104
bool is_local() const
Checks whether the globally referenced element is in the calling unit&#39;s local memory.
T operator++() const
prefix atomically increment value by one
bool compare_exchange(const T &expected, const T &desired) const
Atomically compares the value with the value of expected and if thosei are bitwise-equal, replaces the former with desired.
Reduce operands to their product.
Definition: Operation.h:182
const self_t & operator=(const self_t &other) const
Copy Assignment.
Definition: GlobRef.h:136
dart_ret_t dart_compare_and_swap(dart_gptr_t gptr, const void *value, const void *compare, void *result, dart_datatype_t dtype)
Atomically replace the single value pointed to by gptr with the the value in value if it is equal to ...
GlobRef(const GlobAsyncRef< dash::Atomic< _T >> &gref)
Copy constructor: Implicit if at least one of the following conditions is satisfied: 1) value_type an...
T operator--(int) const
postfix atomically decrement value by one
T fetch_multiply(const T &value) const
Atomic fetch-and-multiply operation on the referenced shared value.
GlobRef(const GlobRef< dash::Atomic< _T >> &gref)
Copy constructor: Implicit if at least one of the following conditions is satisfied: 1) value_type an...
self_t & operator=(const self_t &other) const
Copy Assignment: Copies atomically the value from other.
T operator-=(const T &value) const
atomically decrement value by ref
T fetch_add(const T &value) const
Atomic fetch-and-add operation on the referenced shared value.
GlobRef(dart_gptr_t dart_gptr)
Constructor: Create an atomic reference to a element in global memory.
Definition: GlobAtomicRef.h:63
DART Global pointer type.
Definition: dart_globmem.h:77
T exchange(const T &value) const
Atomically exchanges value.
Type trait for mapping to DART data types.
Definition: Types.h:96
void sub(const T &value) const
DASH specific variant which is faster than fetch_sub but does not return value.
T operator++(int) const
postfix atomically increment value by one
T operator+=(const T &value) const
atomically increment value by ref
dart_ret_t
Return values of functions in the DART interface.
Definition: dart_types.h:30
T fetch_sub(const T &value) const
Atomic fetch-and-sub operation on the referenced shared value.
T operator=(const T &value) const
atomically assigns value
void op(BinaryOp binary_op, const T &value) const
Atomically executes specified operation on the referenced shared value.
Pointer in global memory space with random access arithmetics.
Definition: GlobPtr.h:33
void add(const T &value) const
DASH specific variant which is faster than fetch_add but does not return value.
dart_ret_t dart_fetch_and_op(dart_gptr_t gptr, const void *value, void *result, dart_datatype_t dtype, dart_operation_t op)
Perform an element-wise atomic update on the value of type dtype pointed to by gptr by applying the o...
Replace Value.
Definition: dart_types.h:95
T operator--() const
prefix atomically decrement value by one
GlobRef(const GlobPtr< const_atomic_t, PatternT > &gptr)
Constructor, creates an GlobRef object referencing an element in global memory.
Definition: GlobAtomicRef.h:74
Global value reference for asynchronous / non-blocking operations.
Definition: GlobAtomicRef.h:17
T fetch_op(BinaryOp binary_op, const T &value) const
Atomic fetch-and-op operation on the referenced shared value.
dart_ret_t dart_flush(dart_gptr_t gptr)
Guarantee completion of all outstanding operations involving a segment on a certain unit...