PMDK C++ bindings  1.7.1
This is the C++ bindings documentation for PMDK's libpmemobj.
contiguous_iterator.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 2018-2021, Intel Corporation
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *
11  * * Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in
13  * the documentation and/or other materials provided with the
14  * distribution.
15  *
16  * * Neither the name of the copyright holder nor the names of its
17  * contributors may be used to endorse or promote products derived
18  * from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 
38 #ifndef LIBPMEMOBJ_CPP_ARRAY_ITERATOR_HPP
39 #define LIBPMEMOBJ_CPP_ARRAY_ITERATOR_HPP
40 
41 #include <algorithm>
42 #include <cassert>
43 #include <functional>
44 
46 
47 namespace pmem
48 {
49 
50 namespace obj
51 {
52 
53 namespace experimental
54 {
55 
60 template <typename Iterator, typename Reference, typename Pointer>
65  constexpr contiguous_iterator(Pointer begin) : ptr(begin)
66  {
67  }
68 
72  Reference operator*() const
73  {
74  return *ptr;
75  }
76 
80  Pointer operator->() const
81  {
82  return ptr;
83  }
84 
88  Iterator &
90  {
91  static_cast<Iterator *>(this)->change_by(1);
92  return *static_cast<Iterator *>(this);
93  }
94 
98  Iterator
100  {
101  Iterator tmp(*static_cast<Iterator *>(this));
102  static_cast<Iterator *>(this)->change_by(1);
103  return tmp;
104  }
105 
109  Iterator &
111  {
112  static_cast<Iterator *>(this)->change_by(-1);
113  return *static_cast<Iterator *>(this);
114  }
115 
119  Iterator
121  {
122  Iterator tmp(*static_cast<Iterator *>(this));
123  static_cast<Iterator *>(this)->change_by(-1);
124  return tmp;
125  }
126 
130  Iterator &
131  operator+=(std::ptrdiff_t n)
132  {
133  static_cast<Iterator *>(this)->change_by(n);
134  return *static_cast<Iterator *>(this);
135  }
136 
140  Iterator &
141  operator-=(std::ptrdiff_t n)
142  {
143  static_cast<Iterator *>(this)->change_by(-n);
144  return *static_cast<Iterator *>(this);
145  }
146 
150  Iterator
151  operator+(std::ptrdiff_t n) const
152  {
153  Iterator tmp(*static_cast<const Iterator *>(this));
154  tmp += n;
155  return tmp;
156  }
157 
161  Iterator
162  operator-(std::ptrdiff_t n) const
163  {
164  Iterator tmp(*static_cast<const Iterator *>(this));
165  tmp -= n;
166  return tmp;
167  }
168 
172  friend std::ptrdiff_t
173  operator-(const Iterator &lhs, const Iterator &rhs)
174  {
175  return lhs.ptr - rhs.ptr;
176  }
177 
181  Reference operator[](std::ptrdiff_t n)
182  {
183  return ptr[n];
184  }
185 
186  Pointer
187  get_ptr() const
188  {
189  return ptr;
190  }
191 
192 protected:
198  void
199  change_by(std::ptrdiff_t n)
200  {
201  ptr += n;
202  }
203 
204  Pointer ptr;
205 };
206 
222 template <typename T>
224  : public contiguous_iterator<range_snapshotting_iterator<T>, T &, T *> {
225  using iterator_category = std::random_access_iterator_tag;
226  using value_type = T;
227  using difference_type = std::ptrdiff_t;
228  using reference = T &;
229  using pointer = T *;
231  reference, pointer>;
232 
237  range_snapshotting_iterator(pointer ptr = nullptr,
238  pointer data = nullptr,
239  std::size_t size = 0,
240  std::size_t snapshot_size = 1)
241  : base_type(ptr),
242  data(data),
243  size(size),
244  snapshot_size(snapshot_size)
245  {
246  assert(data <= ptr);
247 
248  if (snapshot_size && ptr)
249  snapshot_range(ptr);
250  }
251 
255  operator const T *()
256  {
257  return this->ptr;
258  }
259 
265  reference operator[](std::ptrdiff_t n)
266  {
267  detail::conditional_add_to_tx(&this->ptr[n]);
268  return base_type::operator[](n);
269  }
270 
274  friend void
276  {
277  std::swap(lhs.ptr, rhs.ptr);
278  std::swap(lhs.data, rhs.data);
279  std::swap(lhs.size, rhs.size);
280  std::swap(lhs.snapshot_size, rhs.snapshot_size);
281  }
282 
283  template <typename Iterator, typename Reference, typename Pointer>
284  friend struct contiguous_iterator;
285 
286 protected:
287  void
288  change_by(std::ptrdiff_t n)
289  {
290  conditional_snapshot_range(this->ptr, n);
292  }
293 
294 private:
295  /*
296  * Conditionally snapshot range of length snapshot_size,
297  * which contain address equal to ptr + diff.
298  */
299  void
300  conditional_snapshot_range(pointer ptr, difference_type diff)
301  {
302  if (snapshot_size == 0)
303  return;
304 
305  auto new_ptr = ptr + diff;
306 
307  /* if new pointer is outside of the array */
308  if (new_ptr < data || new_ptr >= data + size)
309  return;
310 
311  /* if new pointer is in the same range */
312  if (static_cast<std::size_t>(ptr - data) / snapshot_size ==
313  static_cast<std::size_t>(new_ptr - data) / snapshot_size)
314  return;
315 
316  snapshot_range(new_ptr);
317  }
318 
319  void
320  snapshot_range(pointer ptr)
321  {
322  /* align index to snapshot_size */
323  auto range_begin =
324  ptr - static_cast<uint64_t>(ptr - data) % snapshot_size;
325  auto range_size = snapshot_size;
326 
327  if (range_begin + range_size > data + size)
328  range_size = static_cast<uint64_t>(data + size -
329  range_begin);
330 #ifndef NDEBUG
331  verify_range(range_begin, range_size);
332 #endif
333 
334  detail::conditional_add_to_tx(range_begin, range_size);
335  }
336 
337 #ifndef NDEBUG
338  void
339  verify_range(pointer range_begin, uint64_t range_size)
340  {
341  auto range_offset = static_cast<uint64_t>(range_begin - data);
342 
343  assert(range_begin >= data);
344  assert(range_offset % snapshot_size == 0);
345  assert((range_offset + range_size) % snapshot_size == 0 ||
346  range_begin + range_size == data + size);
347  }
348 #endif
349 
350  pointer data;
351  std::size_t size;
352  std::size_t snapshot_size;
353 };
354 
359 template <typename T>
361  : public contiguous_iterator<basic_contiguous_iterator<T>, T &, T *> {
362  using iterator_category = std::random_access_iterator_tag;
363  using value_type = T;
364  using difference_type = std::ptrdiff_t;
365  using reference = T &;
366  using pointer = T *;
368  reference, pointer>;
369 
374  basic_contiguous_iterator(pointer ptr = nullptr) : base_type(ptr)
375  {
376  }
377 
381  operator const T *()
382  {
383  return this->ptr;
384  }
385 
390  reference operator*() const
391  {
392  detail::conditional_add_to_tx(this->ptr);
393  return base_type::operator*();
394  }
395 
400  pointer operator->() const
401  {
402  detail::conditional_add_to_tx(this->ptr);
403  return base_type::operator->();
404  }
405 
411  reference operator[](std::ptrdiff_t n)
412  {
413  detail::conditional_add_to_tx(&this->ptr[n]);
414  return base_type::operator[](n);
415  }
416 
420  friend void
422  {
423  std::swap(lhs.ptr, rhs.ptr);
424  }
425 };
426 
427 } /* namespace experimental */
428 
429 } /* namespace obj */
430 
431 } /* namespace pmem */
432 
433 #endif /* LIBPMEMOBJ_CPP_ARRAY_ITERATOR_HPP */
Non-const iterator which adds elements to a transaction in a bulk.
Definition: contiguous_iterator.hpp:223
Iterator & operator+=(std::ptrdiff_t n)
Addition assignment operator.
Definition: contiguous_iterator.hpp:131
Default non-const iterator which adds element to a transaction on every access.
Definition: contiguous_iterator.hpp:360
reference operator *() const
Dereference operator which adds dereferenced element to a transaction.
Definition: contiguous_iterator.hpp:390
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:237
pmem::obj::experimental::array< T, N >::iterator begin(pmem::obj::experimental::array< T, N > &a)
Non-member begin.
Definition: array.hpp:817
Iterator operator--(int)
Postfix decrement operator.
Definition: contiguous_iterator.hpp:120
friend void swap(range_snapshotting_iterator &lhs, range_snapshotting_iterator &rhs)
Non-member swap function.
Definition: contiguous_iterator.hpp:275
reference operator[](std::ptrdiff_t n)
Element access operator.
Definition: contiguous_iterator.hpp:411
Iterator & operator++()
Prefix increment operator.
Definition: contiguous_iterator.hpp:89
Reference operator[](std::ptrdiff_t n)
Element access operator.
Definition: contiguous_iterator.hpp:181
reference operator[](std::ptrdiff_t n)
Element access operator.
Definition: contiguous_iterator.hpp:265
friend std::ptrdiff_t operator-(const Iterator &lhs, const Iterator &rhs)
Subtraction operator overload Iterator type.
Definition: contiguous_iterator.hpp:173
void change_by(std::ptrdiff_t n)
Function for changing underlying pointer.
Definition: contiguous_iterator.hpp:199
Commonly used functionality.
friend void swap(basic_contiguous_iterator &lhs, basic_contiguous_iterator &rhs)
Non-member swap function.
Definition: contiguous_iterator.hpp:421
Iterator & operator-=(std::ptrdiff_t n)
Subtraction assignment operator.
Definition: contiguous_iterator.hpp:141
pointer operator->() const
Arrow operator which adds underlying element to a transactions.
Definition: contiguous_iterator.hpp:400
basic_contiguous_iterator(pointer ptr=nullptr)
Constructor taking pointer and snapshotting function as arguments.
Definition: contiguous_iterator.hpp:374
Pointer operator->() const
Arrow operator.
Definition: contiguous_iterator.hpp:80
Base class for iterators which satisfies RandomAccessIterator and operate on contiguous memory.
Definition: contiguous_iterator.hpp:61
constexpr contiguous_iterator(Pointer begin)
Constructor taking a pointer.
Definition: contiguous_iterator.hpp:65
Reference operator *() const
Dereference operator.
Definition: contiguous_iterator.hpp:72
Iterator & operator--()
Prefix decrement operator.
Definition: contiguous_iterator.hpp:110
Iterator operator+(std::ptrdiff_t n) const
Addition operator.
Definition: contiguous_iterator.hpp:151
Iterator operator++(int)
Postfix increment operator.
Definition: contiguous_iterator.hpp:99
Iterator operator-(std::ptrdiff_t n) const
Subtraction operator overload for integral type.
Definition: contiguous_iterator.hpp:162