PMDK C++ bindings  1.13.0-git107.g7e59f08f
This is the C++ bindings documentation for PMDK's libpmemobj.
persistent_ptr.hpp
Go to the documentation of this file.
1 // SPDX-License-Identifier: BSD-3-Clause
2 /* Copyright 2015-2021, Intel Corporation */
3 
9 #ifndef LIBPMEMOBJ_CPP_PERSISTENT_PTR_HPP
10 #define LIBPMEMOBJ_CPP_PERSISTENT_PTR_HPP
11 
12 #include <cassert>
13 #include <limits>
14 #include <memory>
15 #include <ostream>
16 
20 #include <libpmemobj++/pool.hpp>
21 #include <libpmemobj/base.h>
22 
23 namespace pmem
24 {
25 
26 namespace obj
27 {
28 
29 template <typename T>
30 class pool;
31 
32 template <typename T>
33 class persistent_ptr;
34 
41 template <>
42 class persistent_ptr<void> : public persistent_ptr_base {
43 public:
44  typedef void element_type;
46 
47  persistent_ptr() = default;
49  persistent_ptr(void *ptr) : persistent_ptr_base(pmemobj_oid(ptr))
50  {
51  }
52 
53  element_type *
54  get() const noexcept
55  {
56  if (this->oid.pool_uuid_lo ==
57  std::numeric_limits<decltype(oid.pool_uuid_lo)>::max())
58  return reinterpret_cast<element_type *>(oid.off);
59  else
60  return static_cast<element_type *>(
61  pmemobj_direct(this->oid));
62  }
63 
64  template <typename Y,
65  typename = typename std::enable_if<
66  std::is_convertible<Y *, void *>::value>::type>
69  {
70  this_type(r).swap(*this);
71 
72  return *this;
73  }
74 
75  explicit operator bool() const noexcept
76  {
77  return get() != nullptr;
78  }
79 };
80 
87 template <>
88 class persistent_ptr<const void> : public persistent_ptr_base {
89 public:
90  typedef const void element_type;
92 
93  persistent_ptr() = default;
95  persistent_ptr(const void *ptr) : persistent_ptr_base(pmemobj_oid(ptr))
96  {
97  }
98 
99  element_type *
100  get() const noexcept
101  {
102  if (this->oid.pool_uuid_lo ==
103  std::numeric_limits<decltype(oid.pool_uuid_lo)>::max())
104  return reinterpret_cast<element_type *>(oid.off);
105  else
106  return static_cast<element_type *>(
107  pmemobj_direct(this->oid));
108  }
109 
110  template <typename Y,
111  typename = typename std::enable_if<
112  std::is_convertible<Y *, const void *>::value>::type>
115  {
116  this_type(r).swap(*this);
117 
118  return *this;
119  }
120 
121  explicit operator bool() const noexcept
122  {
123  return get() != nullptr;
124  }
125 };
126 
152 template <typename T>
154 public:
155  typedef persistent_ptr<T> this_type;
156 
157  template <typename U>
158  friend class persistent_ptr;
159 
164  typedef typename pmem::detail::sp_element<T>::type element_type;
165 
166  persistent_ptr() = default;
168 
169  /*
170  * Constructors
171  */
172 
176  explicit persistent_ptr(persistent_ptr<void> const &rhs) noexcept
177  : persistent_ptr_base(rhs.raw())
178  {
179  }
180 
184  explicit persistent_ptr(persistent_ptr<const void> const &rhs) noexcept
185  : persistent_ptr_base(rhs.raw())
186  {
187  }
188 
198  : persistent_ptr_base(pmemobj_oid(ptr))
199  {
200  verify_type();
201  }
202 
208  template <typename U,
209  typename = typename std::enable_if<
210  !std::is_same<T, U>::value &&
211  std::is_same<typename std::remove_cv<T>::type,
212  U>::value>::type>
214  : persistent_ptr_base(r.oid)
215  {
216  this->oid.off +=
217  static_cast<std::uint64_t>(calculate_offset<U>());
218  verify_type();
219  }
220 
226  template <
227  typename U, typename Dummy = void,
228  typename = typename std::enable_if<
229  !std::is_same<
230  typename std::remove_cv<T>::type,
231  typename std::remove_cv<U>::type>::value &&
232  !std::is_void<U>::value,
233  decltype(static_cast<T *>(std::declval<U *>()))>::type>
235  : persistent_ptr_base(r.oid)
236  {
237  this->oid.off +=
238  static_cast<std::uint64_t>(calculate_offset<U>());
239  verify_type();
240  }
241 
242  /*
243  * Operators
244  */
245 
249  operator persistent_ptr<void>() const noexcept
250  {
251  return this->get();
252  }
253 
257  typename pmem::detail::sp_dereference<T>::type operator*() const
258  noexcept
259  {
260  return *this->get();
261  }
262 
266  typename pmem::detail::sp_member_access<T>::type operator->() const
267  noexcept
268  {
269  return this->get();
270  }
271 
277  template <typename = typename std::enable_if<!std::is_void<T>::value>>
278  typename pmem::detail::sp_array_access<T>::type
279  operator[](std::ptrdiff_t i) const noexcept
280  {
281  assert(i >= 0 &&
282  (i < pmem::detail::sp_extent<T>::value ||
283  pmem::detail::sp_extent<T>::value == 0) &&
284  "persistent array index out of bounds");
285 
286  return this->get()[i];
287  }
288 
292  inline persistent_ptr<T> &
294  {
296  this->oid.off += sizeof(T);
297 
298  return *this;
299  }
300 
304  inline persistent_ptr<T>
306  {
307  PMEMoid noid = this->oid;
308  ++(*this);
309 
310  return persistent_ptr<T>(noid);
311  }
312 
316  inline persistent_ptr<T> &
318  {
320  this->oid.off -= sizeof(T);
321 
322  return *this;
323  }
324 
328  inline persistent_ptr<T>
330  {
331  PMEMoid noid = this->oid;
332  --(*this);
333 
334  return persistent_ptr<T>(noid);
335  }
336 
340  inline persistent_ptr<T> &
341  operator+=(std::ptrdiff_t s)
342  {
344  this->oid.off += static_cast<std::uint64_t>(s) * sizeof(T);
345 
346  return *this;
347  }
348 
352  inline persistent_ptr<T> &
353  operator-=(std::ptrdiff_t s)
354  {
356  this->oid.off -= static_cast<std::uint64_t>(s) * sizeof(T);
357 
358  return *this;
359  }
360 
372  template <typename Y,
373  typename = typename std::enable_if<
374  std::is_convertible<Y *, T *>::value>::type>
377  {
378  this_type(r).swap(*this);
379 
380  return *this;
381  }
382 
386  explicit operator bool() const noexcept
387  {
388  return get() != nullptr;
389  }
390 
391  /*
392  * Persist/flush methods
393  */
394 
400  void
402  {
403  pop.persist(this->get(), sizeof(T));
404  }
405 
412  void
413  persist(void)
414  {
415  pmemobjpool *pop = pmemobj_pool_by_oid(this->raw());
416 
417  if (pop == nullptr)
418  throw pmem::pool_error(
419  "Cannot get pool from persistent pointer");
420 
421  pmemobj_persist(pop, this->get(), sizeof(T));
422  }
423 
429  void
431  {
432  pop.flush(this->get(), sizeof(T));
433  }
434 
441  void
442  flush(void)
443  {
444  pmemobjpool *pop = pmemobj_pool_by_oid(this->raw());
445 
446  if (pop == nullptr)
447  throw pmem::pool_error(
448  "Cannot get pool from persistent pointer");
449 
450  pmemobj_flush(pop, this->get(), sizeof(T));
451  }
452 
453  /*
454  * Pointer traits related.
455  */
456 
465  static persistent_ptr<T>
466  pointer_to(T &ref)
467  {
468  return persistent_ptr<T>(std::addressof(ref), 0);
469  }
470 
478  element_type *
479  get() const noexcept
480  {
481  if (this->oid.pool_uuid_lo ==
482  std::numeric_limits<decltype(oid.pool_uuid_lo)>::max())
483  return reinterpret_cast<element_type *>(oid.off);
484  else
485  return static_cast<element_type *>(
486  pmemobj_direct(this->oid));
487  }
488 
492  template <class U>
494 
499 
503  using bool_type = bool;
504 
512  using iterator_category = std::random_access_iterator_tag;
513 
517  using difference_type = std::ptrdiff_t;
518 
522  using value_type = T;
523 
527  using reference = T &;
528 
533 
534 protected:
538  void
540  {
541  static_assert(!std::is_polymorphic<element_type>::value,
542  "Polymorphic types are not supported");
543  }
544 
553  {
554  if (OID_IS_NULL(oid)) {
555  oid.pool_uuid_lo = std::numeric_limits<decltype(
556  oid.pool_uuid_lo)>::max();
557  oid.off = reinterpret_cast<decltype(oid.off)>(vptr);
558  }
559  }
560 
576  template <typename U>
577  inline ptrdiff_t
579  {
580  static const ptrdiff_t ptr_offset_magic = 0xF00000000000000;
581 
582  static_assert(ptr_offset_magic % alignof(U) == 0, "");
583  static_assert(ptr_offset_magic % alignof(T) == 0, "");
584 
585  U *tmp{reinterpret_cast<U *>(ptr_offset_magic)};
586  T *diff = static_cast<T *>(tmp);
587  return reinterpret_cast<ptrdiff_t>(diff) -
588  reinterpret_cast<ptrdiff_t>(tmp);
589  }
590 };
591 
599 template <class T>
600 inline void
602 {
603  a.swap(b);
604 }
605 
612 template <typename T, typename Y>
613 inline bool
614 operator==(persistent_ptr<T> const &lhs, persistent_ptr<Y> const &rhs) noexcept
615 {
616  return OID_EQUALS(lhs.raw(), rhs.raw());
617 }
618 
623 template <typename T, typename Y>
624 inline bool
625 operator!=(persistent_ptr<T> const &lhs, persistent_ptr<Y> const &rhs) noexcept
626 {
627  return !(lhs == rhs);
628 }
629 
634 template <typename T>
635 inline bool
636 operator==(persistent_ptr<T> const &lhs, std::nullptr_t) noexcept
637 {
638  return lhs.get() == nullptr;
639 }
640 
645 template <typename T>
646 inline bool
647 operator==(std::nullptr_t, persistent_ptr<T> const &lhs) noexcept
648 {
649  return lhs.get() == nullptr;
650 }
651 
656 template <typename T>
657 inline bool
658 operator!=(persistent_ptr<T> const &lhs, std::nullptr_t) noexcept
659 {
660  return lhs.get() != nullptr;
661 }
662 
667 template <typename T>
668 inline bool
669 operator!=(std::nullptr_t, persistent_ptr<T> const &lhs) noexcept
670 {
671  return lhs.get() != nullptr;
672 }
673 
682 template <typename T, typename Y>
683 inline bool
684 operator<(persistent_ptr<T> const &lhs, persistent_ptr<Y> const &rhs) noexcept
685 {
686  if (lhs.raw().pool_uuid_lo == rhs.raw().pool_uuid_lo)
687  return lhs.raw().off < rhs.raw().off;
688  else
689  return lhs.raw().pool_uuid_lo < rhs.raw().pool_uuid_lo;
690 }
691 
698 template <typename T, typename Y>
699 inline bool
700 operator<=(persistent_ptr<T> const &lhs, persistent_ptr<Y> const &rhs) noexcept
701 {
702  return !(rhs < lhs);
703 }
704 
711 template <typename T, typename Y>
712 inline bool
713 operator>(persistent_ptr<T> const &lhs, persistent_ptr<Y> const &rhs) noexcept
714 {
715  return (rhs < lhs);
716 }
717 
724 template <typename T, typename Y>
725 inline bool
726 operator>=(persistent_ptr<T> const &lhs, persistent_ptr<Y> const &rhs) noexcept
727 {
728  return !(lhs < rhs);
729 }
730 
731 /* nullptr comparisons */
732 
737 template <typename T>
738 inline bool
739 operator<(persistent_ptr<T> const &lhs, std::nullptr_t) noexcept
740 {
741  return std::less<typename persistent_ptr<T>::element_type *>()(
742  lhs.get(), nullptr);
743 }
744 
749 template <typename T>
750 inline bool
751 operator<(std::nullptr_t, persistent_ptr<T> const &rhs) noexcept
752 {
753  return std::less<typename persistent_ptr<T>::element_type *>()(
754  nullptr, rhs.get());
755 }
756 
761 template <typename T>
762 inline bool
763 operator<=(persistent_ptr<T> const &lhs, std::nullptr_t) noexcept
764 {
765  return !(nullptr < lhs);
766 }
767 
772 template <typename T>
773 inline bool
774 operator<=(std::nullptr_t, persistent_ptr<T> const &rhs) noexcept
775 {
776  return !(rhs < nullptr);
777 }
778 
783 template <typename T>
784 inline bool
785 operator>(persistent_ptr<T> const &lhs, std::nullptr_t) noexcept
786 {
787  return nullptr < lhs;
788 }
789 
794 template <typename T>
795 inline bool
796 operator>(std::nullptr_t, persistent_ptr<T> const &rhs) noexcept
797 {
798  return rhs < nullptr;
799 }
800 
805 template <typename T>
806 inline bool
807 operator>=(persistent_ptr<T> const &lhs, std::nullptr_t) noexcept
808 {
809  return !(lhs < nullptr);
810 }
811 
816 template <typename T>
817 inline bool
818 operator>=(std::nullptr_t, persistent_ptr<T> const &rhs) noexcept
819 {
820  return !(nullptr < rhs);
821 }
822 
827 template <typename T>
828 inline persistent_ptr<T>
829 operator+(persistent_ptr<T> const &lhs, std::ptrdiff_t s)
830 {
831  PMEMoid noid;
832  noid.pool_uuid_lo = lhs.raw().pool_uuid_lo;
833  noid.off = lhs.raw().off + static_cast<std::uint64_t>(s) * sizeof(T);
834 
835  return persistent_ptr<T>(noid);
836 }
837 
842 template <typename T>
843 inline persistent_ptr<T>
844 operator-(persistent_ptr<T> const &lhs, std::ptrdiff_t s)
845 {
846  PMEMoid noid;
847  noid.pool_uuid_lo = lhs.raw().pool_uuid_lo;
848  noid.off = lhs.raw().off - static_cast<std::uint64_t>(s) * sizeof(T);
849 
850  return persistent_ptr<T>(noid);
851 }
852 
861 template <typename T, typename Y,
862  typename = typename std::enable_if<
863  std::is_same<typename std::remove_cv<T>::type,
864  typename std::remove_cv<Y>::type>::value>>
865 inline ptrdiff_t
867 {
868  assert(lhs.raw().pool_uuid_lo == rhs.raw().pool_uuid_lo);
869  auto d = static_cast<std::ptrdiff_t>(lhs.raw().off - rhs.raw().off);
870 
871  return d / static_cast<std::ptrdiff_t>(sizeof(T));
872 }
873 
878 template <typename T>
879 std::ostream &
880 operator<<(std::ostream &os, persistent_ptr<T> const &pptr)
881 {
882  PMEMoid raw_oid = pptr.raw();
883  os << std::hex << "0x" << raw_oid.pool_uuid_lo << ", 0x" << raw_oid.off
884  << std::dec;
885  return os;
886 }
887 
888 } /* namespace obj */
889 
890 } /* namespace pmem */
891 
892 #endif /* LIBPMEMOBJ_CPP_PERSISTENT_PTR_HPP */
Resides on pmem class.
Definition: p.hpp:36
persistent_ptr const void specialization.
Definition: persistent_ptr.hpp:88
persistent_ptr void specialization.
Definition: persistent_ptr.hpp:42
Persistent_ptr base (non-template) class.
Definition: persistent_ptr_base.hpp:42
void swap(persistent_ptr_base &other)
Swaps two persistent_ptr objects of the same type.
Definition: persistent_ptr_base.hpp:136
persistent_ptr_base() noexcept
Default constructor, zeroes the PMEMoid.
Definition: persistent_ptr_base.hpp:47
const PMEMoid & raw() const noexcept
Get PMEMoid encapsulated by this object.
Definition: persistent_ptr_base.hpp:151
Persistent pointer class.
Definition: persistent_ptr.hpp:153
bool operator==(persistent_ptr< T > const &lhs, std::nullptr_t) noexcept
Equality operator with nullptr.
Definition: persistent_ptr.hpp:636
persistent_ptr(persistent_ptr< void > const &rhs) noexcept
Explicit void specialization of the converting constructor.
Definition: persistent_ptr.hpp:176
void persist(pool_base &pop)
Persists the content of the underlying object.
Definition: persistent_ptr.hpp:401
bool operator>(persistent_ptr< T > const &lhs, std::nullptr_t) noexcept
Compare a persistent_ptr with a null pointer.
Definition: persistent_ptr.hpp:785
bool operator>=(persistent_ptr< T > const &lhs, persistent_ptr< Y > const &rhs) noexcept
Greater or equal than operator.
Definition: persistent_ptr.hpp:726
void persist(void)
Persists what the persistent pointer points to.
Definition: persistent_ptr.hpp:413
void flush(pool_base &pop)
Flushes what the persistent pointer points to.
Definition: persistent_ptr.hpp:430
bool operator!=(std::nullptr_t, persistent_ptr< T > const &lhs) noexcept
Inequality operator with nullptr.
Definition: persistent_ptr.hpp:669
bool bool_type
The used bool_type.
Definition: persistent_ptr.hpp:503
persistent_ptr< T > & operator=(persistent_ptr< Y > const &r)
Converting assignment operator from a different persistent_ptr<>.
Definition: persistent_ptr.hpp:376
persistent_ptr< T > & operator--()
Prefix decrement operator.
Definition: persistent_ptr.hpp:317
bool operator>(std::nullptr_t, persistent_ptr< T > const &rhs) noexcept
Compare a persistent_ptr with a null pointer.
Definition: persistent_ptr.hpp:796
persistent_ptr_base() noexcept
Default constructor, zeroes the PMEMoid.
Definition: persistent_ptr_base.hpp:47
persistent_ptr< T > operator++(int)
Postfix increment operator.
Definition: persistent_ptr.hpp:305
void flush(void)
Flushes what the persistent pointer points to.
Definition: persistent_ptr.hpp:442
pmem::detail::sp_dereference< T >::type operator*() const noexcept
Dereference operator.
Definition: persistent_ptr.hpp:257
persistent_ptr< T > & operator+=(std::ptrdiff_t s)
Addition assignment operator.
Definition: persistent_ptr.hpp:341
pmem::detail::sp_member_access< T >::type operator->() const noexcept
Member access operator.
Definition: persistent_ptr.hpp:266
persistent_ptr(persistent_ptr< const void > const &rhs) noexcept
Explicit const void specialization of the converting constructor.
Definition: persistent_ptr.hpp:184
T & reference
The reference type of the value pointed to by the persistent_ptr.
Definition: persistent_ptr.hpp:527
persistent_ptr< T > & operator-=(std::ptrdiff_t s)
Subtraction assignment operator.
Definition: persistent_ptr.hpp:353
persistent_ptr< T > operator--(int)
Postfix decrement operator.
Definition: persistent_ptr.hpp:329
bool operator==(persistent_ptr< T > const &lhs, persistent_ptr< Y > const &rhs) noexcept
Equality operator.
Definition: persistent_ptr.hpp:614
pmem::detail::sp_array_access< T >::type operator[](std::ptrdiff_t i) const noexcept
Array access operator.
Definition: persistent_ptr.hpp:279
bool operator==(std::nullptr_t, persistent_ptr< T > const &lhs) noexcept
Equality operator with nullptr.
Definition: persistent_ptr.hpp:647
std::random_access_iterator_tag iterator_category
Random access iterator requirements (members)
Definition: persistent_ptr.hpp:512
bool operator!=(persistent_ptr< T > const &lhs, persistent_ptr< Y > const &rhs) noexcept
Inequality operator.
Definition: persistent_ptr.hpp:625
persistent_ptr(element_type *ptr)
Volatile pointer constructor.
Definition: persistent_ptr.hpp:197
pmem::detail::sp_element< T >::type element_type
Type of the actual object with all qualifiers removed, used for easy underlying type access.
Definition: persistent_ptr.hpp:164
T value_type
The type of the value pointed to by the persistent_ptr.
Definition: persistent_ptr.hpp:522
bool operator>=(std::nullptr_t, persistent_ptr< T > const &rhs) noexcept
Compare a persistent_ptr with a null pointer.
Definition: persistent_ptr.hpp:818
bool operator>(persistent_ptr< T > const &lhs, persistent_ptr< Y > const &rhs) noexcept
Greater than operator.
Definition: persistent_ptr.hpp:713
persistent_ptr< T > & operator++()
Prefix increment operator.
Definition: persistent_ptr.hpp:293
void swap(persistent_ptr< T > &a, persistent_ptr< T > &b)
Swaps two persistent_ptr objects of the same type.
Definition: persistent_ptr.hpp:601
persistent_ptr(persistent_ptr< U > const &r) noexcept
Copy constructor from a different persistent_ptr<>.
Definition: persistent_ptr.hpp:213
persistent_ptr(persistent_ptr< U > const &r) noexcept
Copy constructor from a different persistent_ptr<>.
Definition: persistent_ptr.hpp:234
ptrdiff_t calculate_offset() const
Calculate in-object offset for structures with inheritance.
Definition: persistent_ptr.hpp:578
element_type * get() const noexcept
Get the direct pointer.
Definition: persistent_ptr.hpp:479
persistent_ptr< T > operator-(persistent_ptr< T > const &lhs, std::ptrdiff_t s)
Subtraction operator for persistent pointers.
Definition: persistent_ptr.hpp:844
std::ptrdiff_t difference_type
The persistent_ptr difference type.
Definition: persistent_ptr.hpp:517
persistent_ptr< T > pointer
The pointer type.
Definition: persistent_ptr.hpp:532
bool operator!=(persistent_ptr< T > const &lhs, std::nullptr_t) noexcept
Inequality operator with nullptr.
Definition: persistent_ptr.hpp:658
persistent_ptr(element_type *vptr, int)
Private constructor enabling persistent_ptrs to volatile objects.
Definition: persistent_ptr.hpp:552
ptrdiff_t operator-(persistent_ptr< T > const &lhs, persistent_ptr< Y > const &rhs)
Subtraction operator for persistent pointers of identical type.
Definition: persistent_ptr.hpp:866
void verify_type()
Verify if element_type is not polymorphic.
Definition: persistent_ptr.hpp:539
persistent_ptr< T > operator+(persistent_ptr< T > const &lhs, std::ptrdiff_t s)
Addition operator for persistent pointers.
Definition: persistent_ptr.hpp:829
bool operator>=(persistent_ptr< T > const &lhs, std::nullptr_t) noexcept
Compare a persistent_ptr with a null pointer.
Definition: persistent_ptr.hpp:807
static persistent_ptr< T > pointer_to(T &ref)
Create a persistent pointer from a given reference.
Definition: persistent_ptr.hpp:466
The non-template pool base class.
Definition: pool.hpp:51
void flush(const void *addr, size_t len) noexcept
Performs flush operation on a given chunk of memory.
Definition: pool.hpp:317
void persist(const void *addr, size_t len) noexcept
Performs persist operation on a given chunk of memory.
Definition: pool.hpp:280
Custom pool error class.
Definition: pexceptions.hpp:84
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
std::ostream & operator<<(std::ostream &os, const radix_tree< K, V, BV, MtMode > &tree)
Prints tree in DOT format.
Definition: radix_tree.hpp:2843
Persistent memory namespace.
Definition: allocation_flag.hpp:15
Base class for persistent_ptr.
C++ pmemobj pool.
Helper template for persistent ptr specialization.