PMDK C++ bindings  1.13.0-git23.gf49772ac
This is the C++ bindings documentation for PMDK's libpmemobj.
self_relative_ptr.hpp
Go to the documentation of this file.
1 // SPDX-License-Identifier: BSD-3-Clause
2 /* Copyright 2020-2021, Intel Corporation */
3 
9 #ifndef LIBPMEMOBJ_CPP_SELF_RELATIVE_PTR_HPP
10 #define LIBPMEMOBJ_CPP_SELF_RELATIVE_PTR_HPP
11 
15 #include <type_traits>
16 
17 namespace pmem
18 {
19 namespace obj
20 {
21 namespace experimental
22 {
23 
24 template <typename T>
25 class self_relative_ptr;
26 
27 template <>
28 class self_relative_ptr<void> : public self_relative_ptr_base {
29 public:
30  using base_type = self_relative_ptr_base;
31  using this_type = self_relative_ptr;
32  using element_type = void;
33 
34  constexpr self_relative_ptr() noexcept = default;
35 
36  constexpr self_relative_ptr(std::nullptr_t) noexcept
38  {
39  }
40 
41  self_relative_ptr(element_type *ptr) noexcept
42  : self_relative_ptr_base(self_offset(ptr))
43  {
44  }
45 
46  inline element_type *
47  get() const noexcept
48  {
49  return static_cast<element_type *>(
51  }
52 
53 private:
55  self_offset(element_type *ptr) const noexcept
56  {
57  return base_type::pointer_to_offset(static_cast<void *>(ptr));
58  }
59 };
60 
80 template <typename T>
82 public:
85  using element_type = typename pmem::detail::sp_element<T>::type;
86 
94  using iterator_category = std::random_access_iterator_tag;
95 
99  using difference_type = typename base_type::difference_type;
100 
104  using value_type = T;
105 
109  using reference = T &;
110 
111  /*
112  * Constructors
113  */
114 
118  constexpr self_relative_ptr() noexcept = default;
119 
123  constexpr self_relative_ptr(std::nullptr_t) noexcept
125  {
126  }
127 
133  self_relative_ptr(element_type *ptr) noexcept
134  : self_relative_ptr_base(self_offset(ptr))
135  {
136  }
137 
142  : self_relative_ptr_base(self_offset(ptr.get()))
143  {
144  }
145 
153  self_relative_ptr(PMEMoid oid) noexcept
154  : self_relative_ptr_base(self_offset(
155  static_cast<element_type *>(pmemobj_direct(oid))))
156  {
157  }
158 
164  {
165  }
166 
172  template <
173  typename U,
174  typename = typename std::enable_if<
175  !std::is_same<
176  typename std::remove_cv<T>::type,
177  typename std::remove_cv<U>::type>::value &&
178  !std::is_void<U>::value,
179  decltype(static_cast<T *>(std::declval<U *>()))>::type>
181  : self_relative_ptr_base(self_offset(static_cast<T *>(r.get())))
182  {
183  }
184 
186  {
187  verify_type();
188  }
189 
195  inline element_type *
196  get() const noexcept
197  {
198  return static_cast<element_type *>(
200  }
201 
207  {
208  return persistent_ptr<T>{this->get()};
209  }
210 
211  /*
212  * Operators
213  */
214 
218  explicit operator bool() const noexcept
219  {
220  return !is_null();
221  }
222 
226  operator persistent_ptr<T>() const
227  {
228  return to_persistent_ptr();
229  }
230 
234  typename pmem::detail::sp_dereference<T>::type operator*() const
235  noexcept
236  {
237  return *(this->get());
238  }
239 
243  typename pmem::detail::sp_member_access<T>::type operator->() const
244  noexcept
245  {
246  return this->get();
247  }
248 
254  template <typename = typename std::enable_if<!std::is_void<T>::value>>
255  typename pmem::detail::sp_array_access<T>::type
256  operator[](difference_type i) const noexcept
257  {
258  assert(i >= 0 &&
259  (i < pmem::detail::sp_extent<T>::value ||
260  pmem::detail::sp_extent<T>::value == 0) &&
261  "persistent array index out of bounds");
262 
263  return this->get()[i];
264  }
265 
278  {
279  this->base_type::operator=(r);
280  return *this;
281  }
282 
294  template <typename Y,
295  typename = typename std::enable_if<
296  std::is_convertible<Y *, T *>::value>::type>
299  {
300  this_type(r).swap(*this);
301  return *this;
302  }
303 
310  self_relative_ptr &operator=(std::nullptr_t)
311  {
312  detail::conditional_add_to_tx(this);
313  this->offset = self_offset(nullptr);
314  return *this;
315  }
316 
320  inline self_relative_ptr<T> &
322  {
323  detail::conditional_add_to_tx(this);
324  this->offset += static_cast<difference_type>(sizeof(T));
325 
326  return *this;
327  }
328 
332  inline self_relative_ptr<T>
334  {
335  auto copy = *this;
336  ++(*this);
337 
338  return copy;
339  }
340 
344  inline self_relative_ptr<T> &
346  {
347  detail::conditional_add_to_tx(this);
348  this->offset -= static_cast<difference_type>(sizeof(T));
349 
350  return *this;
351  }
352 
356  inline self_relative_ptr<T>
358  {
359  auto copy = *this;
360  --(*this);
361 
362  return copy;
363  }
364 
368  inline self_relative_ptr<T> &
369  operator+=(std::ptrdiff_t s)
370  {
371  detail::conditional_add_to_tx(this);
372  this->offset += s * static_cast<difference_type>(sizeof(T));
373  return *this;
374  }
375 
379  inline self_relative_ptr<T> &
380  operator-=(std::ptrdiff_t s)
381  {
382  detail::conditional_add_to_tx(this);
383  this->offset -= s * static_cast<difference_type>(sizeof(T));
384  return *this;
385  }
386 
387 protected:
391  void
393  {
394  static_assert(!std::is_polymorphic<element_type>::value,
395  "Polymorphic types are not supported");
396  }
397 
398 private:
400  self_offset(element_type *ptr) const noexcept
401  {
402  return base_type::pointer_to_offset(static_cast<void *>(ptr));
403  }
404 };
405 
412 template <class T>
413 inline void
415 {
416  a.swap(b);
417 }
418 
422 template <typename T, typename Y>
423 inline bool
425  self_relative_ptr<Y> const &rhs) noexcept
426 {
427  return lhs.to_byte_pointer() == rhs.to_byte_pointer();
428 }
429 
433 template <typename T, typename Y>
434 inline bool
436  self_relative_ptr<Y> const &rhs) noexcept
437 {
438  return !(lhs == rhs);
439 }
440 
444 template <typename T>
445 inline bool
446 operator==(self_relative_ptr<T> const &lhs, std::nullptr_t) noexcept
447 {
448  return !bool(lhs);
449 }
450 
454 template <typename T>
455 inline bool
456 operator==(std::nullptr_t, self_relative_ptr<T> const &lhs) noexcept
457 {
458  return !bool(lhs);
459 }
460 
464 template <typename T>
465 inline bool
466 operator!=(self_relative_ptr<T> const &lhs, std::nullptr_t) noexcept
467 {
468  return bool(lhs);
469 }
470 
474 template <typename T>
475 inline bool
476 operator!=(std::nullptr_t, self_relative_ptr<T> const &lhs) noexcept
477 {
478  return bool(lhs);
479 }
480 
487 template <typename T, typename Y>
488 inline bool
490  self_relative_ptr<Y> const &rhs) noexcept
491 {
492  return lhs.to_byte_pointer() < rhs.to_byte_pointer();
493 }
494 
500 template <typename T, typename Y>
501 inline bool
503  self_relative_ptr<Y> const &rhs) noexcept
504 {
505  return !(rhs < lhs);
506 }
507 
513 template <typename T, typename Y>
514 inline bool
516  self_relative_ptr<Y> const &rhs) noexcept
517 {
518  return (rhs < lhs);
519 }
520 
526 template <typename T, typename Y>
527 inline bool
529  self_relative_ptr<Y> const &rhs) noexcept
530 {
531  return !(lhs < rhs);
532 }
533 
534 /* nullptr comparisons */
535 
539 template <typename T>
540 inline bool
541 operator<(self_relative_ptr<T> const &lhs, std::nullptr_t) noexcept
542 {
543  return std::less<typename self_relative_ptr<T>::element_type *>()(
544  lhs.get(), nullptr);
545 }
546 
550 template <typename T>
551 inline bool
552 operator<(std::nullptr_t, self_relative_ptr<T> const &rhs) noexcept
553 {
554  return std::less<typename self_relative_ptr<T>::element_type *>()(
555  nullptr, rhs.get());
556 }
557 
561 template <typename T>
562 inline bool
563 operator<=(self_relative_ptr<T> const &lhs, std::nullptr_t) noexcept
564 {
565  return !(nullptr < lhs);
566 }
567 
571 template <typename T>
572 inline bool
573 operator<=(std::nullptr_t, self_relative_ptr<T> const &rhs) noexcept
574 {
575  return !(rhs < nullptr);
576 }
577 
581 template <typename T>
582 inline bool
583 operator>(self_relative_ptr<T> const &lhs, std::nullptr_t) noexcept
584 {
585  return nullptr < lhs;
586 }
587 
591 template <typename T>
592 inline bool
593 operator>(std::nullptr_t, self_relative_ptr<T> const &rhs) noexcept
594 {
595  return rhs < nullptr;
596 }
597 
601 template <typename T>
602 inline bool
603 operator>=(self_relative_ptr<T> const &lhs, std::nullptr_t) noexcept
604 {
605  return !(lhs < nullptr);
606 }
607 
611 template <typename T>
612 inline bool
613 operator>=(std::nullptr_t, self_relative_ptr<T> const &rhs) noexcept
614 {
615  return !(nullptr < rhs);
616 }
617 
621 template <typename T>
622 inline self_relative_ptr<T>
623 operator+(self_relative_ptr<T> const &lhs, std::ptrdiff_t s)
624 {
625  self_relative_ptr<T> ptr = lhs;
626  ptr += s;
627  return ptr;
628 }
629 
633 template <typename T>
634 inline self_relative_ptr<T>
635 operator-(self_relative_ptr<T> const &lhs, std::ptrdiff_t s)
636 {
637  self_relative_ptr<T> ptr = lhs;
638  ptr -= s;
639  return ptr;
640 }
641 
649 template <typename T, typename Y,
650  typename = typename std::enable_if<
651  std::is_same<typename std::remove_cv<T>::type,
652  typename std::remove_cv<Y>::type>::value>>
653 inline ptrdiff_t
655 {
657  static_cast<ptrdiff_t>(sizeof(T));
658 }
659 
663 template <typename T>
664 std::ostream &
665 operator<<(std::ostream &os, self_relative_ptr<T> const &ptr)
666 {
667  os << ptr.to_void_pointer();
668  return os;
669 }
670 
671 } /* namespace experimental */
672 
673 } /* namespace obj */
674 
675 } /* namespace pmem */
676 
677 #endif /* LIBPMEMOBJ_CPP_SELF_RELATIVE_PTR_HPP */
self_relative_ptr base template class
Definition: self_relative_ptr_base_impl.hpp:39
static difference_type distance_between(const self_relative_ptr_base_impl &first, const self_relative_ptr_base_impl &second)
Byte distance between two relative pointers.
Definition: self_relative_ptr_base_impl.hpp:179
void * to_void_pointer() const noexcept
Conversion to void*.
Definition: self_relative_ptr_base_impl.hpp:154
bool is_null() const noexcept
Fast null checking without conversion to void*.
Definition: self_relative_ptr_base_impl.hpp:189
void swap(self_relative_ptr_base_impl &other)
Swaps two self_relative_ptr_base objects of the same type.
Definition: self_relative_ptr_base_impl.hpp:129
self_relative_ptr_base_impl & operator=(self_relative_ptr_base_impl const &r)
Assignment operator.
Definition: self_relative_ptr_base_impl.hpp:100
difference_type pointer_to_offset(const self_relative_ptr_base_impl &ptr) const noexcept
Conversion self_relative_ptr_base to offset from itself.
Definition: self_relative_ptr_base_impl.hpp:235
Persistent self-relative pointer class.
Definition: self_relative_ptr.hpp:81
self_relative_ptr< T > operator++(int)
Postfix increment operator.
Definition: self_relative_ptr.hpp:333
self_relative_ptr< T > & operator+=(std::ptrdiff_t s)
Addition assignment operator.
Definition: self_relative_ptr.hpp:369
pmem::detail::sp_dereference< T >::type operator*() const noexcept
Dereference operator.
Definition: self_relative_ptr.hpp:234
self_relative_ptr(element_type *ptr) noexcept
Volatile pointer constructor.
Definition: self_relative_ptr.hpp:133
T & reference
The reference type of the value pointed to by the self_relative_ptr.
Definition: self_relative_ptr.hpp:109
self_relative_ptr & operator=(const self_relative_ptr &r)
Assignment operator.
Definition: self_relative_ptr.hpp:277
T value_type
The type of the value pointed to by the self_relative_ptr.
Definition: self_relative_ptr.hpp:104
self_relative_ptr(persistent_ptr< T > ptr) noexcept
Constructor from persistent_ptr<T>
Definition: self_relative_ptr.hpp:141
self_relative_ptr(PMEMoid oid) noexcept
PMEMoid constructor.
Definition: self_relative_ptr.hpp:153
self_relative_ptr< T > & operator--()
Prefix decrement operator.
Definition: self_relative_ptr.hpp:345
self_relative_ptr< T > & operator++()
Prefix increment operator.
Definition: self_relative_ptr.hpp:321
void verify_type()
Verify if element_type is not polymorphic.
Definition: self_relative_ptr.hpp:392
self_relative_ptr< T > & operator=(self_relative_ptr< Y > const &r)
Converting assignment operator from a different self_relative_ptr<>.
Definition: self_relative_ptr.hpp:298
self_relative_ptr< T > & operator-=(std::ptrdiff_t s)
Subtraction assignment operator.
Definition: self_relative_ptr.hpp:380
self_relative_ptr< T > operator--(int)
Postfix decrement operator.
Definition: self_relative_ptr.hpp:357
persistent_ptr< T > to_persistent_ptr() const
Conversion to persitent ptr.
Definition: self_relative_ptr.hpp:206
pmem::detail::sp_array_access< T >::type operator[](difference_type i) const noexcept
Array access operator.
Definition: self_relative_ptr.hpp:256
element_type * get() const noexcept
Get the direct pointer.
Definition: self_relative_ptr.hpp:196
self_relative_ptr(const self_relative_ptr &ptr) noexcept
Copy constructor.
Definition: self_relative_ptr.hpp:162
typename base_type::difference_type difference_type
The self_relative_ptr difference type.
Definition: self_relative_ptr.hpp:99
pmem::detail::sp_member_access< T >::type operator->() const noexcept
Member access operator.
Definition: self_relative_ptr.hpp:243
self_relative_ptr(self_relative_ptr< U > const &r) noexcept
Copy constructor from a different self_relative_ptr<>.
Definition: self_relative_ptr.hpp:180
constexpr self_relative_ptr() noexcept=default
Default constructor, equal the nullptr.
self_relative_ptr & operator=(std::nullptr_t)
Nullptr move assignment operator.
Definition: self_relative_ptr.hpp:310
std::random_access_iterator_tag iterator_category
Random access iterator requirements (members)
Definition: self_relative_ptr.hpp:94
Persistent pointer class.
Definition: persistent_ptr.hpp:152
bool operator==(self_relative_ptr< T > const &lhs, self_relative_ptr< Y > const &rhs) noexcept
Equality operator.
Definition: self_relative_ptr.hpp:424
std::ostream & operator<<(std::ostream &os, const radix_tree< K, V, BV, MtMode > &tree)
Prints tree in DOT format.
Definition: radix_tree.hpp:2840
bool operator<=(self_relative_ptr< T > const &lhs, self_relative_ptr< Y > const &rhs) noexcept
Less or equal than operator.
Definition: self_relative_ptr.hpp:502
self_relative_ptr< T > operator+(self_relative_ptr< T > const &lhs, std::ptrdiff_t s)
Addition operator for self-relative pointers.
Definition: self_relative_ptr.hpp:623
void swap(concurrent_map< Key, Value, Comp, Allocator > &lhs, concurrent_map< Key, Value, Comp, Allocator > &rhs)
Non-member swap.
Definition: concurrent_map.hpp:151
self_relative_ptr< T > operator-(self_relative_ptr< T > const &lhs, std::ptrdiff_t s)
Subtraction operator for self-relative pointers.
Definition: self_relative_ptr.hpp:635
bool operator>=(self_relative_ptr< T > const &lhs, self_relative_ptr< Y > const &rhs) noexcept
Greater or equal than operator.
Definition: self_relative_ptr.hpp:528
bool operator!=(self_relative_ptr< T > const &lhs, self_relative_ptr< Y > const &rhs) noexcept
Inequality operator.
Definition: self_relative_ptr.hpp:435
bool operator>(self_relative_ptr< T > const &lhs, self_relative_ptr< Y > const &rhs) noexcept
Greater than operator.
Definition: self_relative_ptr.hpp:515
bool operator<(self_relative_ptr< T > const &lhs, self_relative_ptr< Y > const &rhs) noexcept
Less than operator.
Definition: self_relative_ptr.hpp:489
pmem::detail::self_relative_ptr_base_impl< std::ptrdiff_t > self_relative_ptr_base
self_relative_ptr base (non-template) class
Definition: self_relative_ptr_base.hpp:36
Persistent memory namespace.
Definition: allocation_flag.hpp:15
Persistent smart pointer.
Base class for self_relative_ptr.
Helper template for persistent ptr specialization.