PMDK C++ bindings  1.11
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-2020, 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 
151 template <typename T>
153 public:
155 
156  template <typename U>
157  friend class persistent_ptr;
158 
163  typedef typename pmem::detail::sp_element<T>::type element_type;
164 
165  persistent_ptr() = default;
167 
168  /*
169  * Constructors
170  */
171 
175  explicit persistent_ptr(persistent_ptr<void> const &rhs) noexcept
176  : persistent_ptr_base(rhs.raw())
177  {
178  }
179 
183  explicit persistent_ptr(persistent_ptr<const void> const &rhs) noexcept
184  : persistent_ptr_base(rhs.raw())
185  {
186  }
187 
197  : persistent_ptr_base(pmemobj_oid(ptr))
198  {
199  verify_type();
200  }
201 
207  template <typename U,
208  typename = typename std::enable_if<
209  !std::is_same<T, U>::value &&
210  std::is_same<typename std::remove_cv<T>::type,
211  U>::value>::type>
213  : persistent_ptr_base(r.oid)
214  {
215  this->oid.off +=
216  static_cast<std::uint64_t>(calculate_offset<U>());
217  verify_type();
218  }
219 
225  template <
226  typename U, typename Dummy = void,
227  typename = typename std::enable_if<
228  !std::is_same<
229  typename std::remove_cv<T>::type,
230  typename std::remove_cv<U>::type>::value &&
231  !std::is_void<U>::value,
232  decltype(static_cast<T *>(std::declval<U *>()))>::type>
234  : persistent_ptr_base(r.oid)
235  {
236  this->oid.off +=
237  static_cast<std::uint64_t>(calculate_offset<U>());
238  verify_type();
239  }
240 
241  /*
242  * Operators
243  */
244 
248  operator persistent_ptr<void>() const noexcept
249  {
250  return this->get();
251  }
252 
256  typename pmem::detail::sp_dereference<T>::type operator*() const
257  noexcept
258  {
259  return *this->get();
260  }
261 
265  typename pmem::detail::sp_member_access<T>::type operator->() const
266  noexcept
267  {
268  return this->get();
269  }
270 
276  template <typename = typename std::enable_if<!std::is_void<T>::value>>
277  typename pmem::detail::sp_array_access<T>::type
278  operator[](std::ptrdiff_t i) const noexcept
279  {
280  assert(i >= 0 &&
281  (i < pmem::detail::sp_extent<T>::value ||
282  pmem::detail::sp_extent<T>::value == 0) &&
283  "persistent array index out of bounds");
284 
285  return this->get()[i];
286  }
287 
291  inline persistent_ptr<T> &
293  {
294  detail::conditional_add_to_tx(this);
295  this->oid.off += sizeof(T);
296 
297  return *this;
298  }
299 
303  inline persistent_ptr<T>
305  {
306  PMEMoid noid = this->oid;
307  ++(*this);
308 
309  return persistent_ptr<T>(noid);
310  }
311 
315  inline persistent_ptr<T> &
317  {
318  detail::conditional_add_to_tx(this);
319  this->oid.off -= sizeof(T);
320 
321  return *this;
322  }
323 
327  inline persistent_ptr<T>
329  {
330  PMEMoid noid = this->oid;
331  --(*this);
332 
333  return persistent_ptr<T>(noid);
334  }
335 
339  inline persistent_ptr<T> &
340  operator+=(std::ptrdiff_t s)
341  {
342  detail::conditional_add_to_tx(this);
343  this->oid.off += static_cast<std::uint64_t>(s) * sizeof(T);
344 
345  return *this;
346  }
347 
351  inline persistent_ptr<T> &
352  operator-=(std::ptrdiff_t s)
353  {
354  detail::conditional_add_to_tx(this);
355  this->oid.off -= static_cast<std::uint64_t>(s) * sizeof(T);
356 
357  return *this;
358  }
359 
371  template <typename Y,
372  typename = typename std::enable_if<
373  std::is_convertible<Y *, T *>::value>::type>
376  {
377  this_type(r).swap(*this);
378 
379  return *this;
380  }
381 
382  /*
383  * Bool conversion operator.
384  */
385  explicit operator bool() const noexcept
386  {
387  return get() != nullptr;
388  }
389 
390  /*
391  * Persist/flush methods
392  */
393 
399  void
401  {
402  pop.persist(this->get(), sizeof(T));
403  }
404 
411  void
412  persist(void)
413  {
414  pmemobjpool *pop = pmemobj_pool_by_oid(this->raw());
415 
416  if (pop == nullptr)
417  throw pmem::pool_error(
418  "Cannot get pool from persistent pointer");
419 
420  pmemobj_persist(pop, this->get(), sizeof(T));
421  }
422 
428  void
430  {
431  pop.flush(this->get(), sizeof(T));
432  }
433 
440  void
441  flush(void)
442  {
443  pmemobjpool *pop = pmemobj_pool_by_oid(this->raw());
444 
445  if (pop == nullptr)
446  throw pmem::pool_error(
447  "Cannot get pool from persistent pointer");
448 
449  pmemobj_flush(pop, this->get(), sizeof(T));
450  }
451 
452  /*
453  * Pointer traits related.
454  */
455 
464  static persistent_ptr<T>
465  pointer_to(T &ref)
466  {
467  return persistent_ptr<T>(std::addressof(ref), 0);
468  }
469 
477  element_type *
478  get() const noexcept
479  {
480  if (this->oid.pool_uuid_lo ==
481  std::numeric_limits<decltype(oid.pool_uuid_lo)>::max())
482  return reinterpret_cast<element_type *>(oid.off);
483  else
484  return static_cast<element_type *>(
485  pmemobj_direct(this->oid));
486  }
487 
491  template <class U>
493 
498 
502  using bool_type = bool;
503 
511  using iterator_category = std::random_access_iterator_tag;
512 
516  using difference_type = std::ptrdiff_t;
517 
521  using value_type = T;
522 
526  using reference = T &;
527 
532 
533 protected:
537  void
539  {
540  static_assert(!std::is_polymorphic<element_type>::value,
541  "Polymorphic types are not supported");
542  }
543 
552  {
553  if (OID_IS_NULL(oid)) {
554  oid.pool_uuid_lo = std::numeric_limits<decltype(
555  oid.pool_uuid_lo)>::max();
556  oid.off = reinterpret_cast<decltype(oid.off)>(vptr);
557  }
558  }
559 
575  template <typename U>
576  inline ptrdiff_t
578  {
579  static const ptrdiff_t ptr_offset_magic = 0xDEADBEEF;
580 
581  U *tmp{reinterpret_cast<U *>(ptr_offset_magic)};
582  T *diff = static_cast<T *>(tmp);
583  return reinterpret_cast<ptrdiff_t>(diff) -
584  reinterpret_cast<ptrdiff_t>(tmp);
585  }
586 };
587 
594 template <class T>
595 inline void
597 {
598  a.swap(b);
599 }
600 
606 template <typename T, typename Y>
607 inline bool
608 operator==(persistent_ptr<T> const &lhs, persistent_ptr<Y> const &rhs) noexcept
609 {
610  return OID_EQUALS(lhs.raw(), rhs.raw());
611 }
612 
616 template <typename T, typename Y>
617 inline bool
618 operator!=(persistent_ptr<T> const &lhs, persistent_ptr<Y> const &rhs) noexcept
619 {
620  return !(lhs == rhs);
621 }
622 
626 template <typename T>
627 inline bool
628 operator==(persistent_ptr<T> const &lhs, std::nullptr_t) noexcept
629 {
630  return lhs.get() == nullptr;
631 }
632 
636 template <typename T>
637 inline bool
638 operator==(std::nullptr_t, persistent_ptr<T> const &lhs) noexcept
639 {
640  return lhs.get() == nullptr;
641 }
642 
646 template <typename T>
647 inline bool
648 operator!=(persistent_ptr<T> const &lhs, std::nullptr_t) noexcept
649 {
650  return lhs.get() != nullptr;
651 }
652 
656 template <typename T>
657 inline bool
658 operator!=(std::nullptr_t, persistent_ptr<T> const &lhs) noexcept
659 {
660  return lhs.get() != nullptr;
661 }
662 
670 template <typename T, typename Y>
671 inline bool
672 operator<(persistent_ptr<T> const &lhs, persistent_ptr<Y> const &rhs) noexcept
673 {
674  if (lhs.raw().pool_uuid_lo == rhs.raw().pool_uuid_lo)
675  return lhs.raw().off < rhs.raw().off;
676  else
677  return lhs.raw().pool_uuid_lo < rhs.raw().pool_uuid_lo;
678 }
679 
685 template <typename T, typename Y>
686 inline bool
687 operator<=(persistent_ptr<T> const &lhs, persistent_ptr<Y> const &rhs) noexcept
688 {
689  return !(rhs < lhs);
690 }
691 
697 template <typename T, typename Y>
698 inline bool
699 operator>(persistent_ptr<T> const &lhs, persistent_ptr<Y> const &rhs) noexcept
700 {
701  return (rhs < lhs);
702 }
703 
709 template <typename T, typename Y>
710 inline bool
711 operator>=(persistent_ptr<T> const &lhs, persistent_ptr<Y> const &rhs) noexcept
712 {
713  return !(lhs < rhs);
714 }
715 
716 /* nullptr comparisons */
717 
721 template <typename T>
722 inline bool
723 operator<(persistent_ptr<T> const &lhs, std::nullptr_t) noexcept
724 {
725  return std::less<typename persistent_ptr<T>::element_type *>()(
726  lhs.get(), nullptr);
727 }
728 
732 template <typename T>
733 inline bool
734 operator<(std::nullptr_t, persistent_ptr<T> const &rhs) noexcept
735 {
736  return std::less<typename persistent_ptr<T>::element_type *>()(
737  nullptr, rhs.get());
738 }
739 
743 template <typename T>
744 inline bool
745 operator<=(persistent_ptr<T> const &lhs, std::nullptr_t) noexcept
746 {
747  return !(nullptr < lhs);
748 }
749 
753 template <typename T>
754 inline bool
755 operator<=(std::nullptr_t, persistent_ptr<T> const &rhs) noexcept
756 {
757  return !(rhs < nullptr);
758 }
759 
763 template <typename T>
764 inline bool
765 operator>(persistent_ptr<T> const &lhs, std::nullptr_t) noexcept
766 {
767  return nullptr < lhs;
768 }
769 
773 template <typename T>
774 inline bool
775 operator>(std::nullptr_t, persistent_ptr<T> const &rhs) noexcept
776 {
777  return rhs < nullptr;
778 }
779 
783 template <typename T>
784 inline bool
785 operator>=(persistent_ptr<T> const &lhs, std::nullptr_t) noexcept
786 {
787  return !(lhs < nullptr);
788 }
789 
793 template <typename T>
794 inline bool
795 operator>=(std::nullptr_t, persistent_ptr<T> const &rhs) noexcept
796 {
797  return !(nullptr < rhs);
798 }
799 
803 template <typename T>
804 inline persistent_ptr<T>
805 operator+(persistent_ptr<T> const &lhs, std::ptrdiff_t s)
806 {
807  PMEMoid noid;
808  noid.pool_uuid_lo = lhs.raw().pool_uuid_lo;
809  noid.off = lhs.raw().off + static_cast<std::uint64_t>(s) * sizeof(T);
810 
811  return persistent_ptr<T>(noid);
812 }
813 
817 template <typename T>
818 inline persistent_ptr<T>
819 operator-(persistent_ptr<T> const &lhs, std::ptrdiff_t s)
820 {
821  PMEMoid noid;
822  noid.pool_uuid_lo = lhs.raw().pool_uuid_lo;
823  noid.off = lhs.raw().off - static_cast<std::uint64_t>(s) * sizeof(T);
824 
825  return persistent_ptr<T>(noid);
826 }
827 
835 template <typename T, typename Y,
836  typename = typename std::enable_if<
837  std::is_same<typename std::remove_cv<T>::type,
838  typename std::remove_cv<Y>::type>::value>>
839 inline ptrdiff_t
841 {
842  assert(lhs.raw().pool_uuid_lo == rhs.raw().pool_uuid_lo);
843  auto d = static_cast<std::ptrdiff_t>(lhs.raw().off - rhs.raw().off);
844 
845  return d / static_cast<std::ptrdiff_t>(sizeof(T));
846 }
847 
851 template <typename T>
852 std::ostream &
853 operator<<(std::ostream &os, persistent_ptr<T> const &pptr)
854 {
855  PMEMoid raw_oid = pptr.raw();
856  os << std::hex << "0x" << raw_oid.pool_uuid_lo << ", 0x" << raw_oid.off
857  << std::dec;
858  return os;
859 }
860 
861 } /* namespace obj */
862 
863 } /* namespace pmem */
864 
865 #endif /* LIBPMEMOBJ_CPP_PERSISTENT_PTR_HPP */
pmem::obj::persistent_ptr< T[]>::difference_type
std::ptrdiff_t difference_type
The persistent_ptr difference type.
Definition: persistent_ptr.hpp:516
pmem::obj::operator+
persistent_ptr< T > operator+(persistent_ptr< T > const &lhs, std::ptrdiff_t s)
Addition operator for persistent pointers.
Definition: persistent_ptr.hpp:805
pmem::obj::persistent_ptr::get
element_type * get() const noexcept
Get the direct pointer.
Definition: persistent_ptr.hpp:478
pmem::obj::persistent_ptr< T[]>::reference
T & reference
The reference type of the value pointed to by the persistent_ptr.
Definition: persistent_ptr.hpp:526
pmem::obj::persistent_ptr::calculate_offset
ptrdiff_t calculate_offset() const
Calculate in-object offset for structures with inheritance.
Definition: persistent_ptr.hpp:577
pmem::obj::persistent_ptr::persistent_ptr
persistent_ptr(persistent_ptr< U > const &r) noexcept
Copy constructor from a different persistent_ptr<>.
Definition: persistent_ptr.hpp:212
pmem::pool_error
Custom pool error class.
Definition: pexceptions.hpp:45
pmem::obj::persistent_ptr::flush
void flush(void)
Flushes what the persistent pointer points to.
Definition: persistent_ptr.hpp:441
pmem::obj::pool_base::persist
void persist(const void *addr, size_t len) noexcept
Performs persist operation on a given chunk of memory.
Definition: pool.hpp:283
pmem
Persistent memory namespace.
Definition: allocation_flag.hpp:15
pmem::obj::persistent_ptr< const void >
persistent_ptr const void specialization.
Definition: persistent_ptr.hpp:88
pmem::obj::persistent_ptr< T[]>::value_type
T value_type
The type of the value pointed to by the persistent_ptr.
Definition: persistent_ptr.hpp:521
pmem::obj::persistent_ptr< T[]>::iterator_category
std::random_access_iterator_tag iterator_category
Random access iterator requirements (members)
Definition: persistent_ptr.hpp:511
common.hpp
Commonly used functionality.
pmem::obj::persistent_ptr::operator--
persistent_ptr< T > & operator--()
Prefix decrement operator.
Definition: persistent_ptr.hpp:316
pmem::obj::operator>
bool operator>(const array< T, N > &lhs, const array< T, N > &rhs)
Non-member greater than operator.
Definition: array.hpp:730
pmem::obj::persistent_ptr::operator++
persistent_ptr< T > operator++(int)
Postfix increment operator.
Definition: persistent_ptr.hpp:304
pmem::obj::persistent_ptr::persist
void persist(void)
Persists what the persistent pointer points to.
Definition: persistent_ptr.hpp:412
pmem::obj::persistent_ptr::pointer_to
static persistent_ptr< T > pointer_to(T &ref)
Create a persistent pointer from a given reference.
Definition: persistent_ptr.hpp:465
pmem::obj::persistent_ptr::operator--
persistent_ptr< T > operator--(int)
Postfix decrement operator.
Definition: persistent_ptr.hpp:328
pmem::obj::persistent_ptr_base::swap
void swap(persistent_ptr_base &other)
Swaps two persistent_ptr objects of the same type.
Definition: persistent_ptr_base.hpp:136
pmem::obj::operator>=
bool operator>=(const array< T, N > &lhs, const array< T, N > &rhs)
Non-member greater or equal operator.
Definition: array.hpp:740
pmem::obj::operator==
bool operator==(standard_alloc_policy< T > const &, standard_alloc_policy< T2 > const &)
Determines if memory from another allocator can be deallocated from this one.
Definition: allocator.hpp:420
pmem::obj::persistent_ptr::operator->
pmem::detail::sp_member_access< T >::type operator->() const noexcept
Member access operator.
Definition: persistent_ptr.hpp:265
pmem::obj::persistent_ptr::persistent_ptr
persistent_ptr(persistent_ptr< U > const &r) noexcept
Copy constructor from a different persistent_ptr<>.
Definition: persistent_ptr.hpp:233
pmem::obj::p
Resides on pmem class.
Definition: p.hpp:35
pmem::obj::operator<<
std::ostream & operator<<(std::ostream &os, persistent_ptr< T > const &pptr)
Ostream operator for the persistent pointer.
Definition: persistent_ptr.hpp:853
pmem::obj::persistent_ptr::persistent_ptr
persistent_ptr(persistent_ptr< void > const &rhs) noexcept
Explicit void specialization of the converting constructor.
Definition: persistent_ptr.hpp:175
pmem::obj::persistent_ptr::operator-=
persistent_ptr< T > & operator-=(std::ptrdiff_t s)
Subtraction assignment operator.
Definition: persistent_ptr.hpp:352
pmem::obj::persistent_ptr::operator*
pmem::detail::sp_dereference< T >::type operator*() const noexcept
Dereference operator.
Definition: persistent_ptr.hpp:256
pmem::obj::persistent_ptr::operator++
persistent_ptr< T > & operator++()
Prefix increment operator.
Definition: persistent_ptr.hpp:292
pmem::obj::persistent_ptr::persistent_ptr_base
persistent_ptr_base() noexcept
Default constructor, zeroes the PMEMoid.
Definition: persistent_ptr_base.hpp:47
pool.hpp
C++ pmemobj pool.
pmem::obj::persistent_ptr< void >
persistent_ptr void specialization.
Definition: persistent_ptr.hpp:42
pmem::obj::operator-
persistent_ptr< T > operator-(persistent_ptr< T > const &lhs, std::ptrdiff_t s)
Subtraction operator for persistent pointers.
Definition: persistent_ptr.hpp:819
pmem::obj::swap
void swap(pmem::obj::array< T, N > &lhs, pmem::obj::array< T, N > &rhs)
Non-member swap function.
Definition: array.hpp:880
pmem::obj::operator!=
bool operator!=(const allocator< T, P, Tr > &lhs, const OtherAllocator &rhs)
Determines if memory from another allocator can be deallocated from this one.
Definition: allocator.hpp:536
pmem::obj::persistent_ptr::persist
void persist(pool_base &pop)
Persists the content of the underlying object.
Definition: persistent_ptr.hpp:400
specialization.hpp
Helper template for persistent ptr specialization.
pmem::obj::persistent_ptr::element_type
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:163
pmem::obj::pool_base::flush
void flush(const void *addr, size_t len) noexcept
Performs flush operation on a given chunk of memory.
Definition: pool.hpp:320
pmem::obj::persistent_ptr< T[]>::bool_type
bool bool_type
The used bool_type.
Definition: persistent_ptr.hpp:502
pmem::obj::persistent_ptr
Persistent pointer class.
Definition: persistent_ptr.hpp:152
pmem::obj::persistent_ptr::flush
void flush(pool_base &pop)
Flushes what the persistent pointer points to.
Definition: persistent_ptr.hpp:429
pmem::obj::operator<
bool operator<(const array< T, N > &lhs, const array< T, N > &rhs)
Non-member less than operator.
Definition: array.hpp:719
pmem::obj::persistent_ptr::operator+=
persistent_ptr< T > & operator+=(std::ptrdiff_t s)
Addition assignment operator.
Definition: persistent_ptr.hpp:340
pmem::obj::persistent_ptr::verify_type
void verify_type()
Verify if element_type is not polymorphic.
Definition: persistent_ptr.hpp:538
pmem::obj::operator<=
bool operator<=(const array< T, N > &lhs, const array< T, N > &rhs)
Non-member less or equal operator.
Definition: array.hpp:750
pmem::obj::persistent_ptr::persistent_ptr
persistent_ptr(element_type *vptr, int)
Private constructor enabling persistent_ptrs to volatile objects.
Definition: persistent_ptr.hpp:551
pmem::obj::persistent_ptr::persistent_ptr
persistent_ptr(persistent_ptr< const void > const &rhs) noexcept
Explicit const void specialization of the converting constructor.
Definition: persistent_ptr.hpp:183
pmem::obj::persistent_ptr_base
Persistent_ptr base (non-template) class.
Definition: persistent_ptr_base.hpp:42
pmem::obj::persistent_ptr::persistent_ptr
persistent_ptr(element_type *ptr)
Volatile pointer constructor.
Definition: persistent_ptr.hpp:196
persistent_ptr_base.hpp
Base class for persistent_ptr.
pmem::obj::pool_base
The non-template pool base class.
Definition: pool.hpp:46
pmem::obj::persistent_ptr::operator=
persistent_ptr< T > & operator=(persistent_ptr< Y > const &r)
Converting assignment operator from a different persistent_ptr<>.
Definition: persistent_ptr.hpp:375
pmem::obj::persistent_ptr_base::persistent_ptr_base
persistent_ptr_base() noexcept
Default constructor, zeroes the PMEMoid.
Definition: persistent_ptr_base.hpp:47
pmem::obj::persistent_ptr::operator[]
pmem::detail::sp_array_access< T >::type operator[](std::ptrdiff_t i) const noexcept
Array access operator.
Definition: persistent_ptr.hpp:278