PMDK C++ bindings  1.10.1
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 
182 template <typename T>
184 public:
186 
187  template <typename U>
188  friend class persistent_ptr;
189 
194  typedef typename pmem::detail::sp_element<T>::type element_type;
195 
196  persistent_ptr() = default;
198 
199  /*
200  * Constructors
201  */
202 
206  explicit persistent_ptr(persistent_ptr<void> const &rhs) noexcept
207  : persistent_ptr_base(rhs.raw())
208  {
209  }
210 
214  explicit persistent_ptr(persistent_ptr<const void> const &rhs) noexcept
215  : persistent_ptr_base(rhs.raw())
216  {
217  }
218 
228  : persistent_ptr_base(pmemobj_oid(ptr))
229  {
230  verify_type();
231  }
232 
238  template <typename U,
239  typename = typename std::enable_if<
240  !std::is_same<T, U>::value &&
241  std::is_same<typename std::remove_cv<T>::type,
242  U>::value>::type>
244  : persistent_ptr_base(r.oid)
245  {
246  this->oid.off +=
247  static_cast<std::uint64_t>(calculate_offset<U>());
248  verify_type();
249  }
250 
256  template <
257  typename U, typename Dummy = void,
258  typename = typename std::enable_if<
259  !std::is_same<
260  typename std::remove_cv<T>::type,
261  typename std::remove_cv<U>::type>::value &&
262  !std::is_void<U>::value,
263  decltype(static_cast<T *>(std::declval<U *>()))>::type>
265  : persistent_ptr_base(r.oid)
266  {
267  this->oid.off +=
268  static_cast<std::uint64_t>(calculate_offset<U>());
269  verify_type();
270  }
271 
272  /*
273  * Operators
274  */
275 
279  operator persistent_ptr<void>() const noexcept
280  {
281  return this->get();
282  }
283 
287  typename pmem::detail::sp_dereference<T>::type operator*() const
288  noexcept
289  {
290  return *this->get();
291  }
292 
296  typename pmem::detail::sp_member_access<T>::type operator->() const
297  noexcept
298  {
299  return this->get();
300  }
301 
307  template <typename = typename std::enable_if<!std::is_void<T>::value>>
308  typename pmem::detail::sp_array_access<T>::type
309  operator[](std::ptrdiff_t i) const noexcept
310  {
311  assert(i >= 0 &&
312  (i < pmem::detail::sp_extent<T>::value ||
313  pmem::detail::sp_extent<T>::value == 0) &&
314  "persistent array index out of bounds");
315 
316  return this->get()[i];
317  }
318 
322  inline persistent_ptr<T> &
324  {
325  detail::conditional_add_to_tx(this);
326  this->oid.off += sizeof(T);
327 
328  return *this;
329  }
330 
334  inline persistent_ptr<T>
336  {
337  PMEMoid noid = this->oid;
338  ++(*this);
339 
340  return persistent_ptr<T>(noid);
341  }
342 
346  inline persistent_ptr<T> &
348  {
349  detail::conditional_add_to_tx(this);
350  this->oid.off -= sizeof(T);
351 
352  return *this;
353  }
354 
358  inline persistent_ptr<T>
360  {
361  PMEMoid noid = this->oid;
362  --(*this);
363 
364  return persistent_ptr<T>(noid);
365  }
366 
370  inline persistent_ptr<T> &
371  operator+=(std::ptrdiff_t s)
372  {
373  detail::conditional_add_to_tx(this);
374  this->oid.off += static_cast<std::uint64_t>(s) * sizeof(T);
375 
376  return *this;
377  }
378 
382  inline persistent_ptr<T> &
383  operator-=(std::ptrdiff_t s)
384  {
385  detail::conditional_add_to_tx(this);
386  this->oid.off -= static_cast<std::uint64_t>(s) * sizeof(T);
387 
388  return *this;
389  }
390 
402  template <typename Y,
403  typename = typename std::enable_if<
404  std::is_convertible<Y *, T *>::value>::type>
407  {
408  this_type(r).swap(*this);
409 
410  return *this;
411  }
412 
413  /*
414  * Bool conversion operator.
415  */
416  explicit operator bool() const noexcept
417  {
418  return get() != nullptr;
419  }
420 
421  /*
422  * Persist/flush methods
423  */
424 
430  void
432  {
433  pop.persist(this->get(), sizeof(T));
434  }
435 
442  void
443  persist(void)
444  {
445  pmemobjpool *pop = pmemobj_pool_by_oid(this->raw());
446 
447  if (pop == nullptr)
448  throw pmem::pool_error(
449  "Cannot get pool from persistent pointer");
450 
451  pmemobj_persist(pop, this->get(), sizeof(T));
452  }
453 
459  void
461  {
462  pop.flush(this->get(), sizeof(T));
463  }
464 
471  void
472  flush(void)
473  {
474  pmemobjpool *pop = pmemobj_pool_by_oid(this->raw());
475 
476  if (pop == nullptr)
477  throw pmem::pool_error(
478  "Cannot get pool from persistent pointer");
479 
480  pmemobj_flush(pop, this->get(), sizeof(T));
481  }
482 
483  /*
484  * Pointer traits related.
485  */
486 
495  static persistent_ptr<T>
496  pointer_to(T &ref)
497  {
498  return persistent_ptr<T>(std::addressof(ref), 0);
499  }
500 
508  element_type *
509  get() const noexcept
510  {
511  if (this->oid.pool_uuid_lo ==
512  std::numeric_limits<decltype(oid.pool_uuid_lo)>::max())
513  return reinterpret_cast<element_type *>(oid.off);
514  else
515  return static_cast<element_type *>(
516  pmemobj_direct(this->oid));
517  }
518 
522  template <class U>
524 
529 
533  using bool_type = bool;
534 
542  using iterator_category = std::random_access_iterator_tag;
543 
547  using difference_type = std::ptrdiff_t;
548 
552  using value_type = T;
553 
557  using reference = T &;
558 
563 
564 protected:
568  void
570  {
571  static_assert(!std::is_polymorphic<element_type>::value,
572  "Polymorphic types are not supported");
573  }
574 
583  {
584  if (OID_IS_NULL(oid)) {
585  oid.pool_uuid_lo = std::numeric_limits<decltype(
586  oid.pool_uuid_lo)>::max();
587  oid.off = reinterpret_cast<decltype(oid.off)>(vptr);
588  }
589  }
590 
606  template <typename U>
607  inline ptrdiff_t
609  {
610  static const ptrdiff_t ptr_offset_magic = 0xF00000000000000;
611 
612  static_assert(ptr_offset_magic % alignof(U) == 0, "");
613  static_assert(ptr_offset_magic % alignof(T) == 0, "");
614 
615  U *tmp{reinterpret_cast<U *>(ptr_offset_magic)};
616  T *diff = static_cast<T *>(tmp);
617  return reinterpret_cast<ptrdiff_t>(diff) -
618  reinterpret_cast<ptrdiff_t>(tmp);
619  }
620 };
621 
628 template <class T>
629 inline void
631 {
632  a.swap(b);
633 }
634 
640 template <typename T, typename Y>
641 inline bool
642 operator==(persistent_ptr<T> const &lhs, persistent_ptr<Y> const &rhs) noexcept
643 {
644  return OID_EQUALS(lhs.raw(), rhs.raw());
645 }
646 
650 template <typename T, typename Y>
651 inline bool
652 operator!=(persistent_ptr<T> const &lhs, persistent_ptr<Y> const &rhs) noexcept
653 {
654  return !(lhs == rhs);
655 }
656 
660 template <typename T>
661 inline bool
662 operator==(persistent_ptr<T> const &lhs, std::nullptr_t) noexcept
663 {
664  return lhs.get() == nullptr;
665 }
666 
670 template <typename T>
671 inline bool
672 operator==(std::nullptr_t, persistent_ptr<T> const &lhs) noexcept
673 {
674  return lhs.get() == nullptr;
675 }
676 
680 template <typename T>
681 inline bool
682 operator!=(persistent_ptr<T> const &lhs, std::nullptr_t) noexcept
683 {
684  return lhs.get() != nullptr;
685 }
686 
690 template <typename T>
691 inline bool
692 operator!=(std::nullptr_t, persistent_ptr<T> const &lhs) noexcept
693 {
694  return lhs.get() != nullptr;
695 }
696 
704 template <typename T, typename Y>
705 inline bool
706 operator<(persistent_ptr<T> const &lhs, persistent_ptr<Y> const &rhs) noexcept
707 {
708  if (lhs.raw().pool_uuid_lo == rhs.raw().pool_uuid_lo)
709  return lhs.raw().off < rhs.raw().off;
710  else
711  return lhs.raw().pool_uuid_lo < rhs.raw().pool_uuid_lo;
712 }
713 
719 template <typename T, typename Y>
720 inline bool
721 operator<=(persistent_ptr<T> const &lhs, persistent_ptr<Y> const &rhs) noexcept
722 {
723  return !(rhs < lhs);
724 }
725 
731 template <typename T, typename Y>
732 inline bool
733 operator>(persistent_ptr<T> const &lhs, persistent_ptr<Y> const &rhs) noexcept
734 {
735  return (rhs < lhs);
736 }
737 
743 template <typename T, typename Y>
744 inline bool
745 operator>=(persistent_ptr<T> const &lhs, persistent_ptr<Y> const &rhs) noexcept
746 {
747  return !(lhs < rhs);
748 }
749 
750 /* nullptr comparisons */
751 
755 template <typename T>
756 inline bool
757 operator<(persistent_ptr<T> const &lhs, std::nullptr_t) noexcept
758 {
759  return std::less<typename persistent_ptr<T>::element_type *>()(
760  lhs.get(), nullptr);
761 }
762 
766 template <typename T>
767 inline bool
768 operator<(std::nullptr_t, persistent_ptr<T> const &rhs) noexcept
769 {
770  return std::less<typename persistent_ptr<T>::element_type *>()(
771  nullptr, rhs.get());
772 }
773 
777 template <typename T>
778 inline bool
779 operator<=(persistent_ptr<T> const &lhs, std::nullptr_t) noexcept
780 {
781  return !(nullptr < lhs);
782 }
783 
787 template <typename T>
788 inline bool
789 operator<=(std::nullptr_t, persistent_ptr<T> const &rhs) noexcept
790 {
791  return !(rhs < nullptr);
792 }
793 
797 template <typename T>
798 inline bool
799 operator>(persistent_ptr<T> const &lhs, std::nullptr_t) noexcept
800 {
801  return nullptr < lhs;
802 }
803 
807 template <typename T>
808 inline bool
809 operator>(std::nullptr_t, persistent_ptr<T> const &rhs) noexcept
810 {
811  return rhs < nullptr;
812 }
813 
817 template <typename T>
818 inline bool
819 operator>=(persistent_ptr<T> const &lhs, std::nullptr_t) noexcept
820 {
821  return !(lhs < nullptr);
822 }
823 
827 template <typename T>
828 inline bool
829 operator>=(std::nullptr_t, persistent_ptr<T> const &rhs) noexcept
830 {
831  return !(nullptr < rhs);
832 }
833 
837 template <typename T>
838 inline persistent_ptr<T>
839 operator+(persistent_ptr<T> const &lhs, std::ptrdiff_t s)
840 {
841  PMEMoid noid;
842  noid.pool_uuid_lo = lhs.raw().pool_uuid_lo;
843  noid.off = lhs.raw().off + static_cast<std::uint64_t>(s) * sizeof(T);
844 
845  return persistent_ptr<T>(noid);
846 }
847 
851 template <typename T>
852 inline persistent_ptr<T>
853 operator-(persistent_ptr<T> const &lhs, std::ptrdiff_t s)
854 {
855  PMEMoid noid;
856  noid.pool_uuid_lo = lhs.raw().pool_uuid_lo;
857  noid.off = lhs.raw().off - static_cast<std::uint64_t>(s) * sizeof(T);
858 
859  return persistent_ptr<T>(noid);
860 }
861 
869 template <typename T, typename Y,
870  typename = typename std::enable_if<
871  std::is_same<typename std::remove_cv<T>::type,
872  typename std::remove_cv<Y>::type>::value>>
873 inline ptrdiff_t
875 {
876  assert(lhs.raw().pool_uuid_lo == rhs.raw().pool_uuid_lo);
877  auto d = static_cast<std::ptrdiff_t>(lhs.raw().off - rhs.raw().off);
878 
879  return d / static_cast<std::ptrdiff_t>(sizeof(T));
880 }
881 
885 template <typename T>
886 std::ostream &
887 operator<<(std::ostream &os, persistent_ptr<T> const &pptr)
888 {
889  PMEMoid raw_oid = pptr.raw();
890  os << std::hex << "0x" << raw_oid.pool_uuid_lo << ", 0x" << raw_oid.off
891  << std::dec;
892  return os;
893 }
894 
895 } /* namespace obj */
896 
897 } /* namespace pmem */
898 
899 #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:547
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:839
pmem::obj::persistent_ptr::get
element_type * get() const noexcept
Get the direct pointer.
Definition: persistent_ptr.hpp:509
pmem::obj::persistent_ptr< T[]>::reference
T & reference
The reference type of the value pointed to by the persistent_ptr.
Definition: persistent_ptr.hpp:557
pmem::obj::persistent_ptr::calculate_offset
ptrdiff_t calculate_offset() const
Calculate in-object offset for structures with inheritance.
Definition: persistent_ptr.hpp:608
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:243
pmem::pool_error
Custom pool error class.
Definition: pexceptions.hpp:47
pmem::obj::persistent_ptr::flush
void flush(void)
Flushes what the persistent pointer points to.
Definition: persistent_ptr.hpp:472
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:552
pmem::obj::persistent_ptr< T[]>::iterator_category
std::random_access_iterator_tag iterator_category
Random access iterator requirements (members)
Definition: persistent_ptr.hpp:542
common.hpp
Commonly used functionality.
pmem::obj::persistent_ptr::operator--
persistent_ptr< T > & operator--()
Prefix decrement operator.
Definition: persistent_ptr.hpp:347
pmem::obj::operator>
bool operator>(const array< T, N > &lhs, const array< T, N > &rhs)
Non-member greater than operator.
Definition: array.hpp:734
pmem::obj::persistent_ptr::operator++
persistent_ptr< T > operator++(int)
Postfix increment operator.
Definition: persistent_ptr.hpp:335
pmem::obj::persistent_ptr::persist
void persist(void)
Persists what the persistent pointer points to.
Definition: persistent_ptr.hpp:443
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:496
pmem::obj::persistent_ptr::operator--
persistent_ptr< T > operator--(int)
Postfix decrement operator.
Definition: persistent_ptr.hpp:359
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:744
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:406
pmem::obj::persistent_ptr::operator->
pmem::detail::sp_member_access< T >::type operator->() const noexcept
Member access operator.
Definition: persistent_ptr.hpp:296
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:264
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:887
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:206
pmem::obj::persistent_ptr::operator-=
persistent_ptr< T > & operator-=(std::ptrdiff_t s)
Subtraction assignment operator.
Definition: persistent_ptr.hpp:383
pmem::obj::persistent_ptr::operator*
pmem::detail::sp_dereference< T >::type operator*() const noexcept
Dereference operator.
Definition: persistent_ptr.hpp:287
pmem::obj::persistent_ptr::operator++
persistent_ptr< T > & operator++()
Prefix increment operator.
Definition: persistent_ptr.hpp:323
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:853
pmem::obj::swap
void swap(pmem::obj::array< T, N > &lhs, pmem::obj::array< T, N > &rhs)
Non-member swap function.
Definition: array.hpp:884
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:522
pmem::obj::persistent_ptr::persist
void persist(pool_base &pop)
Persists the content of the underlying object.
Definition: persistent_ptr.hpp:431
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:194
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:533
pmem::obj::persistent_ptr
Persistent pointer class.
Definition: persistent_ptr.hpp:183
pmem::obj::persistent_ptr::flush
void flush(pool_base &pop)
Flushes what the persistent pointer points to.
Definition: persistent_ptr.hpp:460
pmem::obj::operator<
bool operator<(const array< T, N > &lhs, const array< T, N > &rhs)
Non-member less than operator.
Definition: array.hpp:723
pmem::obj::persistent_ptr::operator+=
persistent_ptr< T > & operator+=(std::ptrdiff_t s)
Addition assignment operator.
Definition: persistent_ptr.hpp:371
pmem::obj::persistent_ptr::verify_type
void verify_type()
Verify if element_type is not polymorphic.
Definition: persistent_ptr.hpp:569
pmem::obj::operator<=
bool operator<=(const array< T, N > &lhs, const array< T, N > &rhs)
Non-member less or equal operator.
Definition: array.hpp:754
pmem::obj::persistent_ptr::persistent_ptr
persistent_ptr(element_type *vptr, int)
Private constructor enabling persistent_ptrs to volatile objects.
Definition: persistent_ptr.hpp:582
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:214
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:227
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:406
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:309