PMDK C++ bindings  1.13.0-git107.g7e59f08f
This is the C++ bindings documentation for PMDK's libpmemobj.
contiguous_iterator.hpp
Go to the documentation of this file.
1 // SPDX-License-Identifier: BSD-3-Clause
2 /* Copyright 2018-2021, Intel Corporation */
3 
9 #ifndef LIBPMEMOBJ_CPP_CONTIGUOUS_ITERATOR_HPP
10 #define LIBPMEMOBJ_CPP_CONTIGUOUS_ITERATOR_HPP
11 
12 #include <algorithm>
13 #include <cassert>
14 #include <functional>
15 
17 
18 namespace pmem
19 {
20 
21 namespace detail
22 {
23 
28 template <typename Iterator, typename Reference, typename Pointer>
33  constexpr contiguous_iterator(Pointer begin) : ptr(begin)
34  {
35  }
36 
40  Reference operator*() const
41  {
42  return *ptr;
43  }
44 
48  Pointer operator->() const
49  {
50  return ptr;
51  }
52 
56  Iterator &
58  {
59  static_cast<Iterator *>(this)->change_by(1);
60  return *static_cast<Iterator *>(this);
61  }
62 
66  Iterator
68  {
69  Iterator tmp(*static_cast<Iterator *>(this));
70  static_cast<Iterator *>(this)->change_by(1);
71  return tmp;
72  }
73 
77  Iterator &
79  {
80  static_cast<Iterator *>(this)->change_by(-1);
81  return *static_cast<Iterator *>(this);
82  }
83 
87  Iterator
89  {
90  Iterator tmp(*static_cast<Iterator *>(this));
91  static_cast<Iterator *>(this)->change_by(-1);
92  return tmp;
93  }
94 
98  Iterator &
99  operator+=(std::ptrdiff_t n)
100  {
101  static_cast<Iterator *>(this)->change_by(n);
102  return *static_cast<Iterator *>(this);
103  }
104 
108  Iterator &
109  operator-=(std::ptrdiff_t n)
110  {
111  static_cast<Iterator *>(this)->change_by(-n);
112  return *static_cast<Iterator *>(this);
113  }
114 
118  Iterator
119  operator+(std::ptrdiff_t n) const
120  {
121  Iterator tmp(*static_cast<const Iterator *>(this));
122  tmp += n;
123  return tmp;
124  }
125 
129  Iterator
130  operator-(std::ptrdiff_t n) const
131  {
132  Iterator tmp(*static_cast<const Iterator *>(this));
133  tmp -= n;
134  return tmp;
135  }
136 
140  friend std::ptrdiff_t
141  operator-(const Iterator &lhs, const Iterator &rhs)
142  {
143  return lhs.ptr - rhs.ptr;
144  }
145 
149  Reference operator[](std::ptrdiff_t n)
150  {
151  return ptr[n];
152  }
153 
154  Pointer
155  get_ptr() const
156  {
157  return ptr;
158  }
159 
160 protected:
166  void
167  change_by(std::ptrdiff_t n)
168  {
169  ptr += n;
170  }
171 
172  Pointer ptr;
173 };
174 
190 template <typename T>
192  : public contiguous_iterator<range_snapshotting_iterator<T>, T &, T *> {
193  using iterator_category = std::random_access_iterator_tag;
194  using value_type = T;
195  using difference_type = std::ptrdiff_t;
196  using reference = T &;
197  using pointer = T *;
199  reference, pointer>;
200 
205  range_snapshotting_iterator(pointer ptr = nullptr,
206  pointer data = nullptr,
207  std::size_t size = 0,
208  std::size_t snapshot_size = 1)
209  : base_type(ptr),
210  data(data),
211  size(size),
212  snapshot_size(snapshot_size)
213  {
214  assert(data <= ptr);
215 
216  if (snapshot_size && ptr)
217  snapshot_range(ptr);
218  }
219 
223  operator const T *() const
224  {
225  return this->ptr;
226  }
227 
233  reference operator[](std::ptrdiff_t n)
234  {
235  detail::conditional_add_to_tx(&this->ptr[n], 1,
236  POBJ_XADD_ASSUME_INITIALIZED);
237  return base_type::operator[](n);
238  }
239 
243  friend void
245  {
246  std::swap(lhs.ptr, rhs.ptr);
247  std::swap(lhs.data, rhs.data);
248  std::swap(lhs.size, rhs.size);
249  std::swap(lhs.snapshot_size, rhs.snapshot_size);
250  }
251 
252  template <typename Iterator, typename Reference, typename Pointer>
253  friend struct contiguous_iterator;
254 
255 protected:
256  void
257  change_by(std::ptrdiff_t n)
258  {
259  conditional_snapshot_range(this->ptr, n);
261  }
262 
263 private:
264  /*
265  * Conditionally snapshot range of length snapshot_size,
266  * which contain address equal to ptr + diff.
267  */
268  void
269  conditional_snapshot_range(pointer ptr, difference_type diff)
270  {
271  if (snapshot_size == 0)
272  return;
273 
274  auto new_ptr = ptr + diff;
275 
276  /* if new pointer is outside of the array */
277  if (new_ptr < data || new_ptr >= data + size)
278  return;
279 
280  /* if new pointer is in the same range */
281  if (static_cast<std::size_t>(ptr - data) / snapshot_size ==
282  static_cast<std::size_t>(new_ptr - data) / snapshot_size)
283  return;
284 
285  snapshot_range(new_ptr);
286  }
287 
288  void
289  snapshot_range(pointer ptr)
290  {
291  /* align index to snapshot_size */
292  auto range_begin =
293  ptr - static_cast<uint64_t>(ptr - data) % snapshot_size;
294  auto range_size = snapshot_size;
295 
296  if (range_begin + range_size > data + size)
297  range_size = static_cast<uint64_t>(data + size -
298  range_begin);
299 #ifndef NDEBUG
300  verify_range(range_begin, range_size);
301 #endif
302 
303  detail::conditional_add_to_tx(range_begin, range_size,
304  POBJ_XADD_ASSUME_INITIALIZED);
305  }
306 
307 #ifndef NDEBUG
308  void
309  verify_range(pointer range_begin, uint64_t range_size)
310  {
311  auto range_offset = static_cast<uint64_t>(range_begin - data);
312 
313  assert(range_begin >= data);
314  assert(range_offset % snapshot_size == 0);
315  assert((range_offset + range_size) % snapshot_size == 0 ||
316  range_begin + range_size == data + size);
317  }
318 #endif
319 
320  pointer data;
321  std::size_t size;
322  std::size_t snapshot_size;
323 };
324 
329 template <typename T>
331  : public contiguous_iterator<basic_contiguous_iterator<T>, T &, T *> {
332  using iterator_category = std::random_access_iterator_tag;
333  using value_type = T;
334  using difference_type = std::ptrdiff_t;
335  using reference = T &;
336  using pointer = T *;
338  reference, pointer>;
339 
344  basic_contiguous_iterator(pointer ptr = nullptr) : base_type(ptr)
345  {
346  }
347 
351  operator const T *() const
352  {
353  return this->ptr;
354  }
355 
360  reference operator*() const
361  {
362  detail::conditional_add_to_tx(this->ptr, 1,
363  POBJ_XADD_ASSUME_INITIALIZED);
364  return base_type::operator*();
365  }
366 
371  pointer operator->() const
372  {
373  detail::conditional_add_to_tx(this->ptr, 1,
374  POBJ_XADD_ASSUME_INITIALIZED);
375  return base_type::operator->();
376  }
377 
383  reference operator[](std::ptrdiff_t n)
384  {
385  detail::conditional_add_to_tx(&this->ptr[n], 1,
386  POBJ_XADD_ASSUME_INITIALIZED);
387  return base_type::operator[](n);
388  }
389 
393  friend void
395  {
396  std::swap(lhs.ptr, rhs.ptr);
397  }
398 };
399 
400 } /* namespace detail */
401 
402 } /* namespace pmem */
403 
404 #endif /* LIBPMEMOBJ_CPP_CONTIGUOUS_ITERATOR_HPP */
Commonly used functionality.
void conditional_add_to_tx(const T *that, std::size_t count=1, uint64_t flags=0)
Conditionally add 'count' objects to a transaction.
Definition: common.hpp:176
Persistent memory namespace.
Definition: allocation_flag.hpp:15
Default non-const iterator which adds element to a transaction on every access.
Definition: contiguous_iterator.hpp:331
friend void swap(basic_contiguous_iterator &lhs, basic_contiguous_iterator &rhs)
Non-member swap function.
Definition: contiguous_iterator.hpp:394
basic_contiguous_iterator(pointer ptr=nullptr)
Constructor taking pointer and snapshotting function as arguments.
Definition: contiguous_iterator.hpp:344
pointer operator->() const
Arrow operator which adds underlying element to a transactions.
Definition: contiguous_iterator.hpp:371
reference operator[](std::ptrdiff_t n)
Element access operator.
Definition: contiguous_iterator.hpp:383
reference operator*() const
Dereference operator which adds dereferenced element to a transaction.
Definition: contiguous_iterator.hpp:360
Base class for iterators which satisfies RandomAccessIterator and operate on contiguous memory.
Definition: contiguous_iterator.hpp:29
void change_by(std::ptrdiff_t n)
Function for changing underlying pointer.
Definition: contiguous_iterator.hpp:167
Iterator operator--(int)
Postfix decrement operator.
Definition: contiguous_iterator.hpp:88
Iterator operator-(std::ptrdiff_t n) const
Subtraction operator overload for integral type.
Definition: contiguous_iterator.hpp:130
Iterator & operator+=(std::ptrdiff_t n)
Addition assignment operator.
Definition: contiguous_iterator.hpp:99
Reference operator[](std::ptrdiff_t n)
Element access operator.
Definition: contiguous_iterator.hpp:149
Iterator operator+(std::ptrdiff_t n) const
Addition operator.
Definition: contiguous_iterator.hpp:119
friend std::ptrdiff_t operator-(const Iterator &lhs, const Iterator &rhs)
Subtraction operator overload Iterator type.
Definition: contiguous_iterator.hpp:141
Iterator & operator--()
Prefix decrement operator.
Definition: contiguous_iterator.hpp:78
Iterator operator++(int)
Postfix increment operator.
Definition: contiguous_iterator.hpp:67
Pointer operator->() const
Arrow operator.
Definition: contiguous_iterator.hpp:48
Reference operator*() const
Dereference operator.
Definition: contiguous_iterator.hpp:40
Iterator & operator-=(std::ptrdiff_t n)
Subtraction assignment operator.
Definition: contiguous_iterator.hpp:109
constexpr contiguous_iterator(Pointer begin)
Constructor taking a pointer.
Definition: contiguous_iterator.hpp:33
Iterator & operator++()
Prefix increment operator.
Definition: contiguous_iterator.hpp:57
Non-const iterator which adds elements to a transaction in a bulk.
Definition: contiguous_iterator.hpp:192
friend void swap(range_snapshotting_iterator &lhs, range_snapshotting_iterator &rhs)
Non-member swap function.
Definition: contiguous_iterator.hpp:244
range_snapshotting_iterator(pointer ptr=nullptr, pointer data=nullptr, std::size_t size=0, std::size_t snapshot_size=1)
Constructor taking pointer to data, pointer to the beginning of the array and snapshot_size.
Definition: contiguous_iterator.hpp:205
reference operator[](std::ptrdiff_t n)
Element access operator.
Definition: contiguous_iterator.hpp:233