PMDK C++ bindings 1.13.0
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
23namespace pmem
24{
25
26namespace obj
27{
28
29template <typename T>
30class pool;
31
32template <typename T>
33class persistent_ptr;
34
41template <>
42class persistent_ptr<void> : public persistent_ptr_base {
43public:
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
87template <>
88class persistent_ptr<const void> : public persistent_ptr_base {
89public:
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
151template <typename T>
153public:
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
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>
466 {
467 return persistent_ptr<T>(std::addressof(ref), 0);
468 }
469
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
533protected:
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 = 0xF00000000000000;
580
581 static_assert(ptr_offset_magic % alignof(U) == 0, "");
582 static_assert(ptr_offset_magic % alignof(T) == 0, "");
583
584 U *tmp{reinterpret_cast<U *>(ptr_offset_magic)};
585 T *diff = static_cast<T *>(tmp);
586 return reinterpret_cast<ptrdiff_t>(diff) -
587 reinterpret_cast<ptrdiff_t>(tmp);
588 }
589};
590
597template <class T>
598inline void
600{
601 a.swap(b);
602}
603
609template <typename T, typename Y>
610inline bool
611operator==(persistent_ptr<T> const &lhs, persistent_ptr<Y> const &rhs) noexcept
612{
613 return OID_EQUALS(lhs.raw(), rhs.raw());
614}
615
619template <typename T, typename Y>
620inline bool
621operator!=(persistent_ptr<T> const &lhs, persistent_ptr<Y> const &rhs) noexcept
622{
623 return !(lhs == rhs);
624}
625
629template <typename T>
630inline bool
631operator==(persistent_ptr<T> const &lhs, std::nullptr_t) noexcept
632{
633 return lhs.get() == nullptr;
634}
635
639template <typename T>
640inline bool
641operator==(std::nullptr_t, persistent_ptr<T> const &lhs) noexcept
642{
643 return lhs.get() == nullptr;
644}
645
649template <typename T>
650inline bool
651operator!=(persistent_ptr<T> const &lhs, std::nullptr_t) noexcept
652{
653 return lhs.get() != nullptr;
654}
655
659template <typename T>
660inline bool
661operator!=(std::nullptr_t, persistent_ptr<T> const &lhs) noexcept
662{
663 return lhs.get() != nullptr;
664}
665
673template <typename T, typename Y>
674inline bool
675operator<(persistent_ptr<T> const &lhs, persistent_ptr<Y> const &rhs) noexcept
676{
677 if (lhs.raw().pool_uuid_lo == rhs.raw().pool_uuid_lo)
678 return lhs.raw().off < rhs.raw().off;
679 else
680 return lhs.raw().pool_uuid_lo < rhs.raw().pool_uuid_lo;
681}
682
688template <typename T, typename Y>
689inline bool
690operator<=(persistent_ptr<T> const &lhs, persistent_ptr<Y> const &rhs) noexcept
691{
692 return !(rhs < lhs);
693}
694
700template <typename T, typename Y>
701inline bool
702operator>(persistent_ptr<T> const &lhs, persistent_ptr<Y> const &rhs) noexcept
703{
704 return (rhs < lhs);
705}
706
712template <typename T, typename Y>
713inline bool
714operator>=(persistent_ptr<T> const &lhs, persistent_ptr<Y> const &rhs) noexcept
715{
716 return !(lhs < rhs);
717}
718
719/* nullptr comparisons */
720
724template <typename T>
725inline bool
726operator<(persistent_ptr<T> const &lhs, std::nullptr_t) noexcept
727{
728 return std::less<typename persistent_ptr<T>::element_type *>()(
729 lhs.get(), nullptr);
730}
731
735template <typename T>
736inline bool
737operator<(std::nullptr_t, persistent_ptr<T> const &rhs) noexcept
738{
739 return std::less<typename persistent_ptr<T>::element_type *>()(
740 nullptr, rhs.get());
741}
742
746template <typename T>
747inline bool
748operator<=(persistent_ptr<T> const &lhs, std::nullptr_t) noexcept
749{
750 return !(nullptr < lhs);
751}
752
756template <typename T>
757inline bool
758operator<=(std::nullptr_t, persistent_ptr<T> const &rhs) noexcept
759{
760 return !(rhs < nullptr);
761}
762
766template <typename T>
767inline bool
768operator>(persistent_ptr<T> const &lhs, std::nullptr_t) noexcept
769{
770 return nullptr < lhs;
771}
772
776template <typename T>
777inline bool
778operator>(std::nullptr_t, persistent_ptr<T> const &rhs) noexcept
779{
780 return rhs < nullptr;
781}
782
786template <typename T>
787inline bool
788operator>=(persistent_ptr<T> const &lhs, std::nullptr_t) noexcept
789{
790 return !(lhs < nullptr);
791}
792
796template <typename T>
797inline bool
798operator>=(std::nullptr_t, persistent_ptr<T> const &rhs) noexcept
799{
800 return !(nullptr < rhs);
801}
802
806template <typename T>
807inline persistent_ptr<T>
808operator+(persistent_ptr<T> const &lhs, std::ptrdiff_t s)
809{
810 PMEMoid noid;
811 noid.pool_uuid_lo = lhs.raw().pool_uuid_lo;
812 noid.off = lhs.raw().off + static_cast<std::uint64_t>(s) * sizeof(T);
813
814 return persistent_ptr<T>(noid);
815}
816
820template <typename T>
821inline persistent_ptr<T>
822operator-(persistent_ptr<T> const &lhs, std::ptrdiff_t s)
823{
824 PMEMoid noid;
825 noid.pool_uuid_lo = lhs.raw().pool_uuid_lo;
826 noid.off = lhs.raw().off - static_cast<std::uint64_t>(s) * sizeof(T);
827
828 return persistent_ptr<T>(noid);
829}
830
838template <typename T, typename Y,
839 typename = typename std::enable_if<
840 std::is_same<typename std::remove_cv<T>::type,
841 typename std::remove_cv<Y>::type>::value>>
842inline ptrdiff_t
844{
845 assert(lhs.raw().pool_uuid_lo == rhs.raw().pool_uuid_lo);
846 auto d = static_cast<std::ptrdiff_t>(lhs.raw().off - rhs.raw().off);
847
848 return d / static_cast<std::ptrdiff_t>(sizeof(T));
849}
850
854template <typename T>
855std::ostream &
856operator<<(std::ostream &os, persistent_ptr<T> const &pptr)
857{
858 PMEMoid raw_oid = pptr.raw();
859 os << std::hex << "0x" << raw_oid.pool_uuid_lo << ", 0x" << raw_oid.off
860 << std::dec;
861 return os;
862}
863
864} /* namespace obj */
865
866} /* namespace pmem */
867
868#endif /* LIBPMEMOBJ_CPP_PERSISTENT_PTR_HPP */
Resides on pmem class.
Definition: p.hpp:35
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
const PMEMoid & raw() const noexcept
Get PMEMoid encapsulated by this object.
Definition: persistent_ptr_base.hpp:151
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
Persistent pointer class.
Definition: persistent_ptr.hpp:152
pmem::detail::sp_dereference< T >::type operator*() const noexcept
Dereference operator.
Definition: persistent_ptr.hpp:256
pmem::detail::sp_array_access< T >::type operator[](std::ptrdiff_t i) const noexcept
Array access operator.
Definition: persistent_ptr.hpp:278
element_type * get() const noexcept
Get the direct pointer.
Definition: persistent_ptr.hpp:478
persistent_ptr(persistent_ptr< void > const &rhs) noexcept
Explicit void specialization of the converting constructor.
Definition: persistent_ptr.hpp:175
void persist(pool_base &pop)
Persists the content of the underlying object.
Definition: persistent_ptr.hpp:400
persistent_ptr< T > & operator++()
Prefix increment operator.
Definition: persistent_ptr.hpp:292
void persist(void)
Persists what the persistent pointer points to.
Definition: persistent_ptr.hpp:412
void flush(pool_base &pop)
Flushes what the persistent pointer points to.
Definition: persistent_ptr.hpp:429
bool bool_type
The used bool_type.
Definition: persistent_ptr.hpp:502
static persistent_ptr< T > pointer_to(T &ref)
Create a persistent pointer from a given reference.
Definition: persistent_ptr.hpp:465
persistent_ptr_base() noexcept
Default constructor, zeroes the PMEMoid.
Definition: persistent_ptr_base.hpp:47
void flush(void)
Flushes what the persistent pointer points to.
Definition: persistent_ptr.hpp:441
persistent_ptr< T > operator++(int)
Postfix increment operator.
Definition: persistent_ptr.hpp:304
persistent_ptr(persistent_ptr< const void > const &rhs) noexcept
Explicit const void specialization of the converting constructor.
Definition: persistent_ptr.hpp:183
persistent_ptr< T > & operator-=(std::ptrdiff_t s)
Subtraction assignment operator.
Definition: persistent_ptr.hpp:352
persistent_ptr< T > & operator--()
Prefix decrement operator.
Definition: persistent_ptr.hpp:316
T & reference
The reference type of the value pointed to by the persistent_ptr.
Definition: persistent_ptr.hpp:526
pmem::detail::sp_member_access< T >::type operator->() const noexcept
Member access operator.
Definition: persistent_ptr.hpp:265
std::random_access_iterator_tag iterator_category
Random access iterator requirements (members)
Definition: persistent_ptr.hpp:511
persistent_ptr(element_type *ptr)
Volatile pointer constructor.
Definition: persistent_ptr.hpp:196
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
T value_type
The type of the value pointed to by the persistent_ptr.
Definition: persistent_ptr.hpp:521
persistent_ptr< T > & operator+=(std::ptrdiff_t s)
Addition assignment operator.
Definition: persistent_ptr.hpp:340
persistent_ptr(persistent_ptr< U > const &r) noexcept
Copy constructor from a different persistent_ptr<>.
Definition: persistent_ptr.hpp:212
persistent_ptr(persistent_ptr< U > const &r) noexcept
Copy constructor from a different persistent_ptr<>.
Definition: persistent_ptr.hpp:233
ptrdiff_t calculate_offset() const
Calculate in-object offset for structures with inheritance.
Definition: persistent_ptr.hpp:577
std::ptrdiff_t difference_type
The persistent_ptr difference type.
Definition: persistent_ptr.hpp:516
persistent_ptr(element_type *vptr, int)
Private constructor enabling persistent_ptrs to volatile objects.
Definition: persistent_ptr.hpp:551
persistent_ptr< T > operator--(int)
Postfix decrement operator.
Definition: persistent_ptr.hpp:328
persistent_ptr< T > & operator=(persistent_ptr< Y > const &r)
Converting assignment operator from a different persistent_ptr<>.
Definition: persistent_ptr.hpp:375
void verify_type()
Verify if element_type is not polymorphic.
Definition: persistent_ptr.hpp:538
The non-template pool base class.
Definition: pool.hpp:50
void flush(const void *addr, size_t len) noexcept
Performs flush operation on a given chunk of memory.
Definition: pool.hpp:316
void persist(const void *addr, size_t len) noexcept
Performs persist operation on a given chunk of memory.
Definition: pool.hpp:279
Custom pool error class.
Definition: pexceptions.hpp:45
Commonly used functionality.
bool operator<=(const array< T, N > &lhs, const array< T, N > &rhs)
Non-member less or equal operator.
Definition: array.hpp:779
bool operator<(const array< T, N > &lhs, const array< T, N > &rhs)
Non-member less than operator.
Definition: array.hpp:748
bool operator>=(const array< T, N > &lhs, const array< T, N > &rhs)
Non-member greater or equal operator.
Definition: array.hpp:769
std::ostream & operator<<(std::ostream &os, persistent_ptr< T > const &pptr)
Ostream operator for the persistent pointer.
Definition: persistent_ptr.hpp:856
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
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
bool operator>(const array< T, N > &lhs, const array< T, N > &rhs)
Non-member greater than operator.
Definition: array.hpp:759
persistent_ptr< T > operator-(persistent_ptr< T > const &lhs, std::ptrdiff_t s)
Subtraction operator for persistent pointers.
Definition: persistent_ptr.hpp:822
persistent_ptr< T > operator+(persistent_ptr< T > const &lhs, std::ptrdiff_t s)
Addition operator for persistent pointers.
Definition: persistent_ptr.hpp:808
void swap(pmem::obj::array< T, N > &lhs, pmem::obj::array< T, N > &rhs)
Non-member swap function.
Definition: array.hpp:909
Persistent memory namespace.
Definition: allocation_flag.hpp:15
Base class for persistent_ptr.
C++ pmemobj pool.
Helper template for persistent ptr specialization.