DASH  0.3.0
GlobHeapLocalPtr.h
1 #ifndef DASH__MEMORY__GLOB_HEAP_LOCAL_PTR_H__INCLUDED
2 #define DASH__MEMORY__GLOB_HEAP_LOCAL_PTR_H__INCLUDED
3 
4 #include <dash/dart/if/dart.h>
5 #include <dash/Types.h>
6 
7 #include <dash/Exception.h>
8 #include <dash/internal/Logging.h>
9 
10 #include <dash/Exception.h>
11 #include <dash/memory/internal/GlobHeapMemTypes.h>
12 
13 #include <type_traits>
14 #include <list>
15 #include <vector>
16 #include <iterator>
17 #include <sstream>
18 #include <iostream>
19 #include <memory>
20 
21 
22 namespace dash {
23 
27 template<
28  typename ElementType,
29  typename IndexType,
30  typename PointerType = ElementType *,
31  typename ReferenceType = ElementType & >
33 : public std::iterator<
34  std::random_access_iterator_tag,
35  ElementType,
36  IndexType,
37  PointerType,
38  ReferenceType >
39 {
40  template<typename E_, typename I_, typename P_, typename R_>
41  friend class GlobHeapLocalPtr;
42 
43  template<typename E_, typename I_, typename P_, typename R_>
44  friend std::ostream & dash::operator<<(
45  std::ostream & os,
47 
48 private:
50  self_t;
51 
52 public:
53  typedef IndexType index_type;
54  typedef typename std::make_unsigned<index_type>::type size_type;
55 
57 public:
58  typedef std::random_access_iterator_tag iterator_category;
59  typedef IndexType difference_type;
60  typedef ElementType value_type;
61  typedef ElementType * pointer;
62  typedef ElementType & reference;
63 
64  typedef internal::glob_dynamic_mem_bucket_type<size_type, value_type>
65  bucket_type;
66 
67 private:
68  typedef typename std::list<bucket_type>
69  bucket_list;
70 
71  typedef typename bucket_list::iterator
72  bucket_iterator;
73 
74  typedef typename bucket_list::const_iterator
75  const_bucket_iterator;
76 
77 public:
78  template<typename BucketIter>
80  const BucketIter & bucket_first,
81  const BucketIter & bucket_last,
82  index_type position,
83  const BucketIter & bucket_it,
84  index_type bucket_phase)
85  : _bucket_first(bucket_first),
86  _bucket_last(bucket_last),
87  _idx(position),
88  _bucket_it(bucket_it),
89  _bucket_phase(bucket_phase)
90  { }
91 
92  template<typename BucketIter>
94  const BucketIter & bucket_first,
95  const BucketIter & bucket_last,
96  index_type position)
97  : _bucket_first(bucket_first),
98  _bucket_last(bucket_last),
99  _idx(position),
100  _bucket_it(bucket_first),
101  _bucket_phase(0)
102  {
103  DASH_LOG_TRACE_VAR("GlobHeapLocalPtr(idx)", position);
104 #ifdef DASH_ENABLE_TRACE_LOGGING
105  index_type bucket_idx = 0;
106 #endif
107  for (_bucket_it = _bucket_first;
108  _bucket_it != _bucket_last; ++_bucket_it) {
109  if (position >= _bucket_it->size) {
110  position -= _bucket_it->size;
111  } else {
112  _bucket_phase = position;
113  break;
114  }
115 #ifdef DASH_ENABLE_TRACE_LOGGING
116  ++bucket_idx;
117 #endif
118  }
119  DASH_LOG_TRACE("GlobHeapLocalPtr(idx) >",
120  "bucket:", bucket_idx,
121  "phase:", _bucket_phase);
122  }
123 
124  GlobHeapLocalPtr() = default;
125 
126  GlobHeapLocalPtr(const self_t & other)
127  : _bucket_first(other._bucket_first),
128  _bucket_last(other._bucket_last),
129  _idx(other._idx),
130  _bucket_it(other._bucket_it),
131  _bucket_phase(other._bucket_phase),
132  _is_nullptr(other._is_nullptr)
133  { }
134 
135  self_t & operator=(const self_t & rhs)
136  {
137  if (this != std::addressof(rhs)) {
138  _bucket_first = rhs._bucket_first;
139  _bucket_last = rhs._bucket_last;
140  _idx = rhs._idx;
141  _bucket_it = rhs._bucket_it;
142  _bucket_phase = rhs._bucket_phase;
143  _is_nullptr = rhs._is_nullptr;
144  }
145  return *this;
146  }
147 
151  template<typename I_, typename P_, typename R_>
153  {
154  if (_is_nullptr) {
156  }
158  _bucket_first,
159  _bucket_last,
160  _idx,
161  _bucket_it,
162  _bucket_phase);
163  }
164 
165  GlobHeapLocalPtr(std::nullptr_t)
166  : _is_nullptr(true)
167  { }
168 
169  self_t & operator=(std::nullptr_t)
170  {
171  _is_nullptr = true;
172  return *this;
173  }
174 
175  inline bool operator==(std::nullptr_t) const
176  {
177  return _is_nullptr;
178  }
179 
180  inline bool operator!=(std::nullptr_t) const
181  {
182  return !_is_nullptr;
183  }
184 
188  reference operator*()
189  {
190  DASH_ASSERT(!_is_nullptr);
191  if (_bucket_phase > _bucket_it->size) {
192  DASH_THROW(dash::exception::OutOfRange,
193  "dereferenced position " << _idx << " is out of range: " <<
194  "bucket phase: " << _bucket_phase << ", " <<
195  "bucket size: " << _bucket_it->size);
196  }
197  return _bucket_it->lptr[_bucket_phase];
198  }
199 
203  reference operator[](index_type offset)
204  {
205  DASH_ASSERT(!_is_nullptr);
206  if (_bucket_phase + offset < _bucket_it->size) {
207  // element is in bucket currently referenced by this iterator:
208  return _bucket_it->lptr[_bucket_phase + offset];
209  } else {
210  // find bucket containing element at given offset:
211  for (auto b_it = _bucket_it; b_it != _bucket_last; ++b_it) {
212  if (offset >= b_it->size) {
213  offset -= b_it->size;
214  } else if (offset < b_it->size) {
215  return b_it->lptr[offset];
216  }
217  }
218  }
219  DASH_THROW(dash::exception::OutOfRange,
220  "dereferenced position " << _idx + offset << " " <<
221  "is out of range: pointer position: " << _idx << ", " <<
222  "offset: " << offset);
223  }
224 
232  explicit operator pointer() const
233  {
234  DASH_LOG_TRACE("GlobHeapLocalPtr.pointer()");
235  pointer lptr = nullptr;
236  if (_is_nullptr) {
237  DASH_LOG_TRACE("GlobHeapLocalPtr.pointer", "is nullptr");
238  } else {
239  auto bucket_size = _bucket_it->size;
240  // This iterator type represents a local pointer so no bounds checks
241  // have to be performed in pointer arithmetics.
242  // Moving a pointer to out-of-bounds address is allowed, however
243  // dereferencing it will lead to segfault. This is a prerequisite for
244  // many common pointer arithmetic use cases.
245  // Example:
246  // value = *((globmem.lend() + 2) - 3);
247  // is a valid operation and equivalent to
248  // value = *(globmem.lend() + (2 - 3));
249  // as it creates a temporary pointer to an address beyond _lend (+2)
250  // which is then moved back into valid memory range (-3).
251  if (_bucket_it == _bucket_last) {
252  DASH_LOG_TRACE("GlobHeapLocalPtr.pointer", "position at lend");
253  } else if (_bucket_phase >= bucket_size) {
254  DASH_LOG_TRACE("GlobHeapLocalPtr.pointer",
255  "bucket size:", bucket_size, ",",
256  "bucket phase:", _bucket_phase);
257  DASH_LOG_TRACE("GlobHeapLocalPtr.pointer",
258  "note: iterator position out of bounds (lend?)");
259  }
260  lptr = _bucket_it->lptr + _bucket_phase;
261  }
262  DASH_LOG_TRACE_VAR("GlobHeapLocalPtr.pointer >", lptr);
263  return lptr;
264  }
265 
266  self_t & operator++()
267  {
268  increment(1);
269  return *this;
270  }
271 
272  self_t & operator--()
273  {
274  decrement(1);
275  return *this;
276  }
277 
278  self_t operator++(int)
279  {
280  auto res = *this;
281  increment(1);
282  return res;
283  }
284 
285  self_t operator--(int)
286  {
287  auto res = *this;
288  decrement(1);
289  return res;
290  }
291 
292  self_t & operator+=(int offset)
293  {
294  increment(offset);
295  return *this;
296  }
297 
298  self_t & operator-=(int offset)
299  {
300  decrement(offset);
301  return *this;
302  }
303 
304  self_t operator+(int offset) const
305  {
306  auto res = *this;
307  res += offset;
308  return res;
309  }
310 
311  self_t operator-(int offset) const
312  {
313  auto res = *this;
314  res -= offset;
315  return res;
316  }
317 
318  inline index_type operator+(
319  const self_t & other) const
320  {
321  return _idx + other._idx;
322  }
323 
324  inline index_type operator-(
325  const self_t & other) const
326  {
327  return _idx - other._idx;
328  }
329 
330  template<typename E_, typename I_, typename P_, typename R_>
331  inline bool operator<(const GlobHeapLocalPtr<E_,I_,P_,R_> & other) const
332  {
333  return (_idx < other._idx);
334  }
335 
336  template<typename E_, typename I_, typename P_, typename R_>
337  inline bool operator<=(const GlobHeapLocalPtr<E_,I_,P_,R_> & other) const
338  {
339  return (_idx <= other._idx);
340  }
341 
342  template<typename E_, typename I_, typename P_, typename R_>
343  inline bool operator>(const GlobHeapLocalPtr<E_,I_,P_,R_> & other) const
344  {
345  return (_idx > other._idx);
346  }
347 
348  template<typename E_, typename I_, typename P_, typename R_>
349  inline bool operator>=(const GlobHeapLocalPtr<E_,I_,P_,R_> & other) const
350  {
351  return (_idx >= other._idx);
352  }
353 
354  template<typename E_, typename I_, typename P_, typename R_>
355  inline bool operator==(const GlobHeapLocalPtr<E_,I_,P_,R_> & other) const
356  {
357  return (this == std::addressof(other) || _idx == other._idx);
358  }
359 
360  template<typename E_, typename I_, typename P_, typename R_>
361  inline bool operator!=(const GlobHeapLocalPtr<E_,I_,P_,R_> & other) const
362  {
363  return !(*this == other);
364  }
365 
371  constexpr bool is_local() const
372  {
373  return true;
374  }
375 
379  index_type pos() const
380  {
381  return _idx;
382  }
383 
384 private:
388  void increment(int offset)
389  {
390  DASH_ASSERT(!_is_nullptr);
391  _idx += offset;
392  if (_bucket_phase + offset < _bucket_it->size) {
393  // element is in bucket currently referenced by this iterator:
394  _bucket_phase += offset;
395  } else {
396  // find bucket containing element at given offset:
397  for (; _bucket_it != _bucket_last; ++_bucket_it) {
398  if (offset >= _bucket_it->size) {
399  offset -= _bucket_it->size;
400  } else if (offset < _bucket_it->size) {
401  _bucket_phase = offset;
402  break;
403  }
404  }
405  }
406  // end iterator
407  if (_bucket_it == _bucket_last) {
408  _bucket_phase = offset;
409  }
410  }
411 
415  void decrement(int offset)
416  {
417  DASH_ASSERT(!_is_nullptr);
418  if (offset > _idx) {
419  DASH_THROW(dash::exception::OutOfRange,
420  "offset " << offset << " is out of range");
421  }
422  _idx -= offset;
423  if (offset <= _bucket_phase) {
424  // element is in bucket currently referenced by this iterator:
425  _bucket_phase -= offset;
426  } else {
427  offset -= _bucket_phase;
428  // find bucket containing element at given offset:
429  for (; _bucket_it != _bucket_first; --_bucket_it) {
430  if (offset >= _bucket_it->size) {
431  offset -= _bucket_it->size;
432  } else if (offset < _bucket_it->size) {
433  _bucket_phase = _bucket_it->size - offset;
434  break;
435  }
436  }
437  }
438  if (_bucket_it == _bucket_first) {
439  _bucket_phase = _bucket_it->size - offset;
440  }
441  if (false) {
442  DASH_THROW(dash::exception::OutOfRange,
443  "offset " << offset << " is out of range");
444  }
445  }
446 
447 private:
448  bucket_iterator _bucket_first;
449  bucket_iterator _bucket_last;
450  index_type _idx = 0;
451  bucket_iterator _bucket_it;
452  index_type _bucket_phase = 0;
453  bool _is_nullptr = false;
454 
455 }; // class GlobHeapLocalPtr
456 
464 template<
465  typename ElementType,
466  typename IndexType,
467  class Pointer,
468  class Reference>
469 auto distance(
472  ElementType, IndexType, Pointer, Reference> & first,
475  ElementType, IndexType, Pointer, Reference> & last)
476 -> IndexType
477 {
478  return last - first;
479 }
480 
481 template<
482  typename ElementType,
483  typename IndexType,
484  class Pointer,
485  class Reference>
486 std::ostream & operator<<(
487  std::ostream & os,
489  ElementType, IndexType, Pointer, Reference> & it)
490 {
491  std::ostringstream ss;
492  auto * lptr = static_cast<ElementType *>(it);
493  ss << "dash::GlobHeapLocalPtr<"
494  << typeid(ElementType).name() << ">"
495  << "("
496  << "idx:" << it._idx << ", "
497  << "bp:" << it._bucket_phase << ", "
498  << "lptr:" << lptr
499  << ")";
500  return operator<<(os, ss.str());
501 }
502 
503 } // namespace dash
504 
505 #endif // DASH__MEMORY__GLOB_HEAP_LOCAL_PTR_H__INCLUDED
size_t size()
Return the number of units in the global team.
This class is a simple memory pool which holds allocates elements of size ValueType.
Definition: AllOf.h:8
constexpr bool is_local() const
Whether the pointer references an element in local memory space.
index_type pos() const
Position of the pointer relative to its referenced memory space.
Iterator on local buckets.
Returns second operand.
Definition: Operation.h:201
std::random_access_iterator_tag iterator_category
Type definitions required for std::iterator_traits:
reference operator*()
Dereference operator.
reference operator[](index_type offset)
Random access operator.
dash::gptrdiff_t distance(GlobPtr< T, MemSpaceT > gbegin, GlobPtr< T, MemSpaceT > gend)
Returns the number of hops from gbegin to gend.
Definition: GlobPtr.h:547