PMDK C++ bindings  1.7.1
This is the C++ bindings documentation for PMDK's libpmemobj.
persistent_ptr.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 2015-2019, Intel Corporation
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *
11  * * Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in
13  * the documentation and/or other materials provided with the
14  * distribution.
15  *
16  * * Neither the name of the copyright holder nor the names of its
17  * contributors may be used to endorse or promote products derived
18  * from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 
38 #ifndef LIBPMEMOBJ_CPP_PERSISTENT_PTR_HPP
39 #define LIBPMEMOBJ_CPP_PERSISTENT_PTR_HPP
40 
41 #include <cassert>
42 #include <limits>
43 #include <memory>
44 #include <ostream>
45 
49 #include <libpmemobj++/pool.hpp>
50 #include <libpmemobj.h>
51 
52 namespace pmem
53 {
54 
55 namespace obj
56 {
57 
58 template <typename T>
59 class pool;
60 
61 template <typename T>
62 class persistent_ptr;
63 
64 /*
65  * persistent_ptr void specialization.
66  */
67 template <>
68 class persistent_ptr<void> : public detail::persistent_ptr_base<void> {
69 public:
70  persistent_ptr() = default;
73 };
74 
75 /*
76  * persistent_ptr const void specialization.
77  */
78 template <>
79 class persistent_ptr<const void>
80  : public detail::persistent_ptr_base<const void> {
81 public:
82  persistent_ptr() = default;
85 };
86 
131 template <typename T>
132 class persistent_ptr : public detail::persistent_ptr_base<T> {
133 public:
134  persistent_ptr() = default;
136 
140  explicit persistent_ptr(persistent_ptr<void> const &rhs) noexcept
141  : detail::persistent_ptr_base<T>(rhs.raw())
142  {
143  }
144 
148  explicit persistent_ptr(persistent_ptr<const void> const &rhs) noexcept
149  : detail::persistent_ptr_base<T>(rhs.raw())
150  {
151  }
152 
156  operator persistent_ptr<void>() const noexcept
157  {
158  return this->get();
159  }
160 
164  typename pmem::detail::sp_dereference<T>::type operator*() const
165  noexcept
166  {
167  return *this->get();
168  }
169 
173  typename pmem::detail::sp_member_access<T>::type operator->() const
174  noexcept
175  {
176  return this->get();
177  }
178 
184  template <typename = typename std::enable_if<!std::is_void<T>::value>>
185  typename pmem::detail::sp_array_access<T>::type
186  operator[](std::ptrdiff_t i) const noexcept
187  {
188  assert(i >= 0 &&
189  (i < pmem::detail::sp_extent<T>::value ||
190  pmem::detail::sp_extent<T>::value == 0) &&
191  "persistent array index out of bounds");
192 
193  return this->get()[i];
194  }
195 
199  inline persistent_ptr<T> &
201  {
202  detail::conditional_add_to_tx(this);
203  this->oid.off += sizeof(T);
204 
205  return *this;
206  }
207 
211  inline persistent_ptr<T>
213  {
214  PMEMoid noid = this->oid;
215  ++(*this);
216 
217  return persistent_ptr<T>(noid);
218  }
219 
223  inline persistent_ptr<T> &
225  {
226  detail::conditional_add_to_tx(this);
227  this->oid.off -= sizeof(T);
228 
229  return *this;
230  }
231 
235  inline persistent_ptr<T>
237  {
238  PMEMoid noid = this->oid;
239  --(*this);
240 
241  return persistent_ptr<T>(noid);
242  }
243 
247  inline persistent_ptr<T> &
248  operator+=(std::ptrdiff_t s)
249  {
250  detail::conditional_add_to_tx(this);
251  this->oid.off += static_cast<std::uint64_t>(s) * sizeof(T);
252 
253  return *this;
254  }
255 
259  inline persistent_ptr<T> &
260  operator-=(std::ptrdiff_t s)
261  {
262  detail::conditional_add_to_tx(this);
263  this->oid.off -= static_cast<std::uint64_t>(s) * sizeof(T);
264 
265  return *this;
266  }
267 
273  void
275  {
276  pop.persist(this->get(), sizeof(T));
277  }
278 
285  void
286  persist(void)
287  {
288  pmemobjpool *pop = pmemobj_pool_by_oid(this->raw());
289 
290  if (pop == nullptr)
291  throw pool_error(
292  "Cannot get pool from persistent pointer");
293 
294  pmemobj_persist(pop, this->get(), sizeof(T));
295  }
296 
302  void
304  {
305  pop.flush(this->get(), sizeof(T));
306  }
307 
314  void
315  flush(void)
316  {
317  pmemobjpool *pop = pmemobj_pool_by_oid(this->raw());
318 
319  if (pop == nullptr)
320  throw pool_error(
321  "Cannot get pool from persistent pointer");
322 
323  pmemobj_flush(pop, this->get(), sizeof(T));
324  }
325 
326  /*
327  * Pointer traits related.
328  */
329 
338  static persistent_ptr<T>
339  pointer_to(T &ref)
340  {
341  return persistent_ptr<T>(std::addressof(ref), 0);
342  }
343 
347  template <class U>
349 
354 
358  using bool_type = bool;
359 
360  /*
361  * Random access iterator requirements (members)
362  */
363 
367  using iterator_category = std::random_access_iterator_tag;
368 
372  using difference_type = std::ptrdiff_t;
373 
377  using value_type = T;
378 
382  using reference = T &;
383 
388 };
389 
396 template <class T>
397 inline void
399 {
400  a.swap(b);
401 }
402 
408 template <typename T, typename Y>
409 inline bool
410 operator==(persistent_ptr<T> const &lhs, persistent_ptr<Y> const &rhs) noexcept
411 {
412  return OID_EQUALS(lhs.raw(), rhs.raw());
413 }
414 
418 template <typename T, typename Y>
419 inline bool
420 operator!=(persistent_ptr<T> const &lhs, persistent_ptr<Y> const &rhs) noexcept
421 {
422  return !(lhs == rhs);
423 }
424 
428 template <typename T>
429 inline bool
430 operator==(persistent_ptr<T> const &lhs, std::nullptr_t) noexcept
431 {
432  return lhs.get() == nullptr;
433 }
434 
438 template <typename T>
439 inline bool
440 operator==(std::nullptr_t, persistent_ptr<T> const &lhs) noexcept
441 {
442  return lhs.get() == nullptr;
443 }
444 
448 template <typename T>
449 inline bool
450 operator!=(persistent_ptr<T> const &lhs, std::nullptr_t) noexcept
451 {
452  return lhs.get() != nullptr;
453 }
454 
458 template <typename T>
459 inline bool
460 operator!=(std::nullptr_t, persistent_ptr<T> const &lhs) noexcept
461 {
462  return lhs.get() != nullptr;
463 }
464 
472 template <typename T, typename Y>
473 inline bool
474 operator<(persistent_ptr<T> const &lhs, persistent_ptr<Y> const &rhs) noexcept
475 {
476  if (lhs.raw().pool_uuid_lo == rhs.raw().pool_uuid_lo)
477  return lhs.raw().off < rhs.raw().off;
478  else
479  return lhs.raw().pool_uuid_lo < rhs.raw().pool_uuid_lo;
480 }
481 
487 template <typename T, typename Y>
488 inline bool
489 operator<=(persistent_ptr<T> const &lhs, persistent_ptr<Y> const &rhs) noexcept
490 {
491  return !(rhs < lhs);
492 }
493 
499 template <typename T, typename Y>
500 inline bool
501 operator>(persistent_ptr<T> const &lhs, persistent_ptr<Y> const &rhs) noexcept
502 {
503  return (rhs < lhs);
504 }
505 
511 template <typename T, typename Y>
512 inline bool
513 operator>=(persistent_ptr<T> const &lhs, persistent_ptr<Y> const &rhs) noexcept
514 {
515  return !(lhs < rhs);
516 }
517 
518 /* nullptr comparisons */
519 
523 template <typename T>
524 inline bool
525 operator<(persistent_ptr<T> const &lhs, std::nullptr_t) noexcept
526 {
527  return std::less<typename persistent_ptr<T>::element_type *>()(
528  lhs.get(), nullptr);
529 }
530 
534 template <typename T>
535 inline bool
536 operator<(std::nullptr_t, persistent_ptr<T> const &rhs) noexcept
537 {
538  return std::less<typename persistent_ptr<T>::element_type *>()(
539  nullptr, rhs.get());
540 }
541 
545 template <typename T>
546 inline bool
547 operator<=(persistent_ptr<T> const &lhs, std::nullptr_t) noexcept
548 {
549  return !(nullptr < lhs);
550 }
551 
555 template <typename T>
556 inline bool
557 operator<=(std::nullptr_t, persistent_ptr<T> const &rhs) noexcept
558 {
559  return !(rhs < nullptr);
560 }
561 
565 template <typename T>
566 inline bool
567 operator>(persistent_ptr<T> const &lhs, std::nullptr_t) noexcept
568 {
569  return nullptr < lhs;
570 }
571 
575 template <typename T>
576 inline bool
577 operator>(std::nullptr_t, persistent_ptr<T> const &rhs) noexcept
578 {
579  return rhs < nullptr;
580 }
581 
585 template <typename T>
586 inline bool
587 operator>=(persistent_ptr<T> const &lhs, std::nullptr_t) noexcept
588 {
589  return !(lhs < nullptr);
590 }
591 
595 template <typename T>
596 inline bool
597 operator>=(std::nullptr_t, persistent_ptr<T> const &rhs) noexcept
598 {
599  return !(nullptr < rhs);
600 }
601 
605 template <typename T>
606 inline persistent_ptr<T>
607 operator+(persistent_ptr<T> const &lhs, std::ptrdiff_t s)
608 {
609  PMEMoid noid;
610  noid.pool_uuid_lo = lhs.raw().pool_uuid_lo;
611  noid.off = lhs.raw().off + static_cast<std::uint64_t>(s) * sizeof(T);
612 
613  return persistent_ptr<T>(noid);
614 }
615 
619 template <typename T>
620 inline persistent_ptr<T>
621 operator-(persistent_ptr<T> const &lhs, std::ptrdiff_t s)
622 {
623  PMEMoid noid;
624  noid.pool_uuid_lo = lhs.raw().pool_uuid_lo;
625  noid.off = lhs.raw().off - static_cast<std::uint64_t>(s) * sizeof(T);
626 
627  return persistent_ptr<T>(noid);
628 }
629 
637 template <typename T, typename Y,
638  typename = typename std::enable_if<
639  std::is_same<typename std::remove_cv<T>::type,
640  typename std::remove_cv<Y>::type>::value>>
641 inline ptrdiff_t
643 {
644  assert(lhs.raw().pool_uuid_lo == rhs.raw().pool_uuid_lo);
645  auto d = static_cast<std::ptrdiff_t>(lhs.raw().off - rhs.raw().off);
646 
647  return d / static_cast<std::ptrdiff_t>(sizeof(T));
648 }
649 
653 template <typename T>
654 std::ostream &
655 operator<<(std::ostream &os, persistent_ptr<T> const &pptr)
656 {
657  PMEMoid raw_oid = pptr.raw();
658  os << std::hex << "0x" << raw_oid.pool_uuid_lo << ", 0x" << raw_oid.off
659  << std::dec;
660  return os;
661 }
662 
663 } /* namespace obj */
664 
665 } /* namespace pmem */
666 
667 #endif /* LIBPMEMOBJ_CPP_PERSISTENT_PTR_HPP */
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:400
persistent_ptr< T > & operator++()
Prefix increment operator.
Definition: persistent_ptr.hpp:200
Persistent_ptr base class.
Definition: persistent_ptr_base.hpp:68
void persist(void)
Persists what the persistent pointer points to.
Definition: persistent_ptr.hpp:286
Helper template for persistent ptr specialization.
Persistent pointer class.
Definition: common.hpp:119
pmem::detail::sp_member_access< T >::type operator->() const noexcept
Member access operator.
Definition: persistent_ptr.hpp:173
The non-template pool base class.
Definition: pool.hpp:67
Custom pool error class.
Definition: pexceptions.hpp:53
persistent_ptr< T > & operator-=(std::ptrdiff_t s)
Subtraction assignment operator.
Definition: persistent_ptr.hpp:260
persistent_ptr(persistent_ptr< const void > const &rhs) noexcept
Explicit const void specialization of the converting constructor.
Definition: persistent_ptr.hpp:148
persistent_ptr< T > operator++(int)
Postfix increment operator.
Definition: persistent_ptr.hpp:212
void persist(pool_base &pop)
Persists the content of the underlying object.
Definition: persistent_ptr.hpp:274
bool bool_type
The used bool_type.
Definition: persistent_ptr.hpp:358
void flush(pool_base &pop)
Flushes what the persistent pointer points to.
Definition: persistent_ptr.hpp:303
PMEMobj pool class.
Definition: persistent_ptr.hpp:59
persistent_ptr< T > operator--(int)
Postfix decrement operator.
Definition: persistent_ptr.hpp:236
persistent_ptr< T > operator+(persistent_ptr< T > const &lhs, std::ptrdiff_t s)
Addition operator for persistent pointers.
Definition: persistent_ptr.hpp:607
Commonly used functionality.
pmem::detail::sp_dereference< T >::type operator *() const noexcept
Dereference operator.
Definition: persistent_ptr.hpp:164
std::random_access_iterator_tag iterator_category
The persistent_ptr iterator category.
Definition: persistent_ptr.hpp:367
persistent_ptr< T > & operator--()
Prefix decrement operator.
Definition: persistent_ptr.hpp:224
persistent_ptr< T > & operator+=(std::ptrdiff_t s)
Addition assignment operator.
Definition: persistent_ptr.hpp:248
void flush(void)
Flushes what the persistent pointer points to.
Definition: persistent_ptr.hpp:315
void persist(const void *addr, size_t len) noexcept
Performs persist operation on a given chunk of memory.
Definition: pool.hpp:284
pmem::detail::sp_array_access< T >::type operator[](std::ptrdiff_t i) const noexcept
Array access operator.
Definition: persistent_ptr.hpp:186
static persistent_ptr< T > pointer_to(T &ref)
Create a persistent pointer from a given reference.
Definition: persistent_ptr.hpp:339
persistent_ptr< T > operator-(persistent_ptr< T > const &lhs, std::ptrdiff_t s)
Subtraction operator for persistent pointers.
Definition: persistent_ptr.hpp:621
std::ostream & operator<<(std::ostream &os, persistent_ptr< T > const &pptr)
Ostream operator for the persistent pointer.
Definition: persistent_ptr.hpp:655
const PMEMoid & raw() const noexcept
Get PMEMoid encapsulated by this object.
Definition: persistent_ptr_base.hpp:304
Resides on pmem class.
Definition: p.hpp:64
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:516
T value_type
The type of the value pointed to by the persistent_ptr.
Definition: persistent_ptr.hpp:377
void flush(const void *addr, size_t len) noexcept
Performs flush operation on a given chunk of memory.
Definition: pool.hpp:320
element_type * get() const noexcept
Get a direct pointer.
Definition: persistent_ptr_base.hpp:286
Base class for persistent_ptr.
std::ptrdiff_t difference_type
The persistent_ptr difference type.
Definition: persistent_ptr.hpp:372
persistent_ptr(persistent_ptr< void > const &rhs) noexcept
Explicit void specialization of the converting constructor.
Definition: persistent_ptr.hpp:140
C++ pmemobj pool.
T & reference
The reference type of the value pointed to by the persistent_ptr.
Definition: persistent_ptr.hpp:382