PMDK C++ bindings  1.2.0
This is the C++ bindings documentation for PMDK's libpmemobj.
 All Classes Files Functions Variables Typedefs Friends Pages
persistent_ptr.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 2015-2018, 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 
101 template <typename T>
102 class persistent_ptr : public detail::persistent_ptr_base<T> {
103 public:
104  persistent_ptr() = default;
106 
110  explicit persistent_ptr(persistent_ptr<void> const &rhs) noexcept
111  : detail::persistent_ptr_base<T>(rhs.raw())
112  {
113  }
114 
118  explicit persistent_ptr(persistent_ptr<const void> const &rhs) noexcept
119  : detail::persistent_ptr_base<T>(rhs.raw())
120  {
121  }
122 
126  operator persistent_ptr<void>() const noexcept
127  {
128  return this->get();
129  }
130 
134  typename pmem::detail::sp_dereference<T>::type operator*() const
135  noexcept
136  {
137  return *this->get();
138  }
139 
143  typename pmem::detail::sp_member_access<T>::type operator->() const
144  noexcept
145  {
146  return this->get();
147  }
148 
154  template <typename = typename std::enable_if<!std::is_void<T>::value>>
155  typename pmem::detail::sp_array_access<T>::type
156  operator[](std::ptrdiff_t i) const noexcept
157  {
158  assert(i >= 0 &&
159  (i < pmem::detail::sp_extent<T>::value ||
160  pmem::detail::sp_extent<T>::value == 0) &&
161  "persistent array index out of bounds");
162 
163  return this->get()[i];
164  }
165 
169  inline persistent_ptr<T> &
171  {
172  detail::conditional_add_to_tx(this);
173  this->oid.off += sizeof(T);
174 
175  return *this;
176  }
177 
181  inline persistent_ptr<T>
183  {
184  PMEMoid noid = this->oid;
185  ++(*this);
186 
187  return persistent_ptr<T>(noid);
188  }
189 
193  inline persistent_ptr<T> &
195  {
196  detail::conditional_add_to_tx(this);
197  this->oid.off -= sizeof(T);
198 
199  return *this;
200  }
201 
205  inline persistent_ptr<T>
207  {
208  PMEMoid noid = this->oid;
209  --(*this);
210 
211  return persistent_ptr<T>(noid);
212  }
213 
217  inline persistent_ptr<T> &
218  operator+=(std::ptrdiff_t s)
219  {
220  detail::conditional_add_to_tx(this);
221  this->oid.off += static_cast<std::uint64_t>(s) * sizeof(T);
222 
223  return *this;
224  }
225 
229  inline persistent_ptr<T> &
230  operator-=(std::ptrdiff_t s)
231  {
232  detail::conditional_add_to_tx(this);
233  this->oid.off -= static_cast<std::uint64_t>(s) * sizeof(T);
234 
235  return *this;
236  }
237 
243  void
245  {
246  pop.persist(this->get(), sizeof(T));
247  }
248 
255  void
256  persist(void)
257  {
258  pmemobjpool *pop = pmemobj_pool_by_oid(this->raw());
259 
260  if (pop == nullptr)
261  throw pool_error("Cannot get pool from "
262  "persistent pointer");
263 
264  pmemobj_persist(pop, this->get(), sizeof(T));
265  }
266 
272  void
274  {
275  pop.flush(this->get(), sizeof(T));
276  }
277 
284  void
285  flush(void)
286  {
287  pmemobjpool *pop = pmemobj_pool_by_oid(this->raw());
288 
289  if (pop == nullptr)
290  throw pool_error("Cannot get pool from "
291  "persistent pointer");
292 
293  pmemobj_flush(pop, this->get(), sizeof(T));
294  }
295 
296  /*
297  * Pointer traits related.
298  */
299 
308  static persistent_ptr<T>
309  pointer_to(T &ref)
310  {
311  return persistent_ptr<T>(std::addressof(ref), 0);
312  }
313 
317  template <class U>
319 
324 
328  using bool_type = bool;
329 
330  /*
331  * Random access iterator requirements (members)
332  */
333 
337  using iterator_category = std::random_access_iterator_tag;
338 
342  using difference_type = std::ptrdiff_t;
343 
347  using value_type = T;
348 
352  using reference = T &;
353 
358 };
359 
366 template <class T>
367 inline void
369 {
370  a.swap(b);
371 }
372 
378 template <typename T, typename Y>
379 inline bool
380 operator==(persistent_ptr<T> const &lhs, persistent_ptr<Y> const &rhs) noexcept
381 {
382  return OID_EQUALS(lhs.raw(), rhs.raw());
383 }
384 
388 template <typename T, typename Y>
389 inline bool
390 operator!=(persistent_ptr<T> const &lhs, persistent_ptr<Y> const &rhs) noexcept
391 {
392  return !(lhs == rhs);
393 }
394 
398 template <typename T>
399 inline bool
400 operator==(persistent_ptr<T> const &lhs, std::nullptr_t) noexcept
401 {
402  return lhs.get() == nullptr;
403 }
404 
408 template <typename T>
409 inline bool
410 operator==(std::nullptr_t, persistent_ptr<T> const &lhs) noexcept
411 {
412  return lhs.get() == nullptr;
413 }
414 
418 template <typename T>
419 inline bool
420 operator!=(persistent_ptr<T> const &lhs, std::nullptr_t) noexcept
421 {
422  return lhs.get() != nullptr;
423 }
424 
428 template <typename T>
429 inline bool
430 operator!=(std::nullptr_t, persistent_ptr<T> const &lhs) noexcept
431 {
432  return lhs.get() != nullptr;
433 }
434 
442 template <typename T, typename Y>
443 inline bool
444 operator<(persistent_ptr<T> const &lhs, persistent_ptr<Y> const &rhs) noexcept
445 {
446  if (lhs.raw().pool_uuid_lo == rhs.raw().pool_uuid_lo)
447  return lhs.raw().off < rhs.raw().off;
448  else
449  return lhs.raw().pool_uuid_lo < rhs.raw().pool_uuid_lo;
450 }
451 
457 template <typename T, typename Y>
458 inline bool
459 operator<=(persistent_ptr<T> const &lhs, persistent_ptr<Y> const &rhs) noexcept
460 {
461  return !(rhs < lhs);
462 }
463 
469 template <typename T, typename Y>
470 inline bool
471 operator>(persistent_ptr<T> const &lhs, persistent_ptr<Y> const &rhs) noexcept
472 {
473  return (rhs < lhs);
474 }
475 
481 template <typename T, typename Y>
482 inline bool
483 operator>=(persistent_ptr<T> const &lhs, persistent_ptr<Y> const &rhs) noexcept
484 {
485  return !(lhs < rhs);
486 }
487 
488 /* nullptr comparisons */
489 
493 template <typename T>
494 inline bool
495 operator<(persistent_ptr<T> const &lhs, std::nullptr_t) noexcept
496 {
497  return std::less<typename persistent_ptr<T>::element_type *>()(
498  lhs.get(), nullptr);
499 }
500 
504 template <typename T>
505 inline bool
506 operator<(std::nullptr_t, persistent_ptr<T> const &rhs) noexcept
507 {
508  return std::less<typename persistent_ptr<T>::element_type *>()(
509  nullptr, rhs.get());
510 }
511 
515 template <typename T>
516 inline bool
517 operator<=(persistent_ptr<T> const &lhs, std::nullptr_t) noexcept
518 {
519  return !(nullptr < lhs);
520 }
521 
525 template <typename T>
526 inline bool
527 operator<=(std::nullptr_t, persistent_ptr<T> const &rhs) noexcept
528 {
529  return !(rhs < nullptr);
530 }
531 
535 template <typename T>
536 inline bool
537 operator>(persistent_ptr<T> const &lhs, std::nullptr_t) noexcept
538 {
539  return nullptr < lhs;
540 }
541 
545 template <typename T>
546 inline bool
547 operator>(std::nullptr_t, persistent_ptr<T> const &rhs) noexcept
548 {
549  return rhs < nullptr;
550 }
551 
555 template <typename T>
556 inline bool
557 operator>=(persistent_ptr<T> const &lhs, std::nullptr_t) noexcept
558 {
559  return !(lhs < nullptr);
560 }
561 
565 template <typename T>
566 inline bool
567 operator>=(std::nullptr_t, persistent_ptr<T> const &rhs) noexcept
568 {
569  return !(nullptr < rhs);
570 }
571 
575 template <typename T>
576 inline persistent_ptr<T>
577 operator+(persistent_ptr<T> const &lhs, std::ptrdiff_t s)
578 {
579  PMEMoid noid;
580  noid.pool_uuid_lo = lhs.raw().pool_uuid_lo;
581  noid.off = lhs.raw().off + static_cast<std::uint64_t>(s) * sizeof(T);
582 
583  return persistent_ptr<T>(noid);
584 }
585 
589 template <typename T>
590 inline persistent_ptr<T>
591 operator-(persistent_ptr<T> const &lhs, std::ptrdiff_t s)
592 {
593  PMEMoid noid;
594  noid.pool_uuid_lo = lhs.raw().pool_uuid_lo;
595  noid.off = lhs.raw().off - static_cast<std::uint64_t>(s) * sizeof(T);
596 
597  return persistent_ptr<T>(noid);
598 }
599 
607 template <typename T, typename Y,
608  typename = typename std::enable_if<
609  std::is_same<typename std::remove_cv<T>::type,
610  typename std::remove_cv<Y>::type>::value>>
611 inline ptrdiff_t
612 operator-(persistent_ptr<T> const &lhs, persistent_ptr<Y> const &rhs)
613 {
614  assert(lhs.raw().pool_uuid_lo == rhs.raw().pool_uuid_lo);
615  auto d = static_cast<std::ptrdiff_t>(lhs.raw().off - rhs.raw().off);
616 
617  return d / static_cast<std::ptrdiff_t>(sizeof(T));
618 }
619 
623 template <typename T>
624 std::ostream &
625 operator<<(std::ostream &os, persistent_ptr<T> const &pptr)
626 {
627  PMEMoid raw_oid = pptr.raw();
628  os << std::hex << "0x" << raw_oid.pool_uuid_lo << ", 0x" << raw_oid.off
629  << std::dec;
630  return os;
631 }
632 
633 } /* namespace obj */
634 
635 } /* namespace pmem */
636 
637 #endif /* LIBPMEMOBJ_CPP_PERSISTENT_PTR_HPP */
persistent_ptr< T > & operator++()
Prefix increment operator.
Definition: persistent_ptr.hpp:170
Persistent_ptr base class.
Definition: persistent_ptr_base.hpp:68
void persist(void)
Persists what the persistent pointer points to.
Definition: persistent_ptr.hpp:256
Helper template for persistent ptr specialization.
Persistent pointer class.
Definition: common.hpp:59
pmem::detail::sp_member_access< T >::type operator->() const noexcept
Member access operator.
Definition: persistent_ptr.hpp:143
The non-template pool base class.
Definition: pool.hpp:66
Custom pool error class.
Definition: pexceptions.hpp:53
persistent_ptr< T > & operator-=(std::ptrdiff_t s)
Subtraction assignment operator.
Definition: persistent_ptr.hpp:230
persistent_ptr(persistent_ptr< const void > const &rhs) noexcept
Explicit const void specialization of the converting constructor.
Definition: persistent_ptr.hpp:118
persistent_ptr< T > operator++(int)
Postfix increment operator.
Definition: persistent_ptr.hpp:182
void persist(pool_base &pop)
Persists the content of the underlying object.
Definition: persistent_ptr.hpp:244
bool bool_type
The used bool_type.
Definition: persistent_ptr.hpp:328
void flush(pool_base &pop)
Flushes what the persistent pointer points to.
Definition: persistent_ptr.hpp:273
PMEMobj pool class.
Definition: persistent_ptr.hpp:59
persistent_ptr< T > operator--(int)
Postfix decrement operator.
Definition: persistent_ptr.hpp:206
Commonly used functionality.
std::random_access_iterator_tag iterator_category
The persistent_ptr iterator category.
Definition: persistent_ptr.hpp:337
persistent_ptr< T > & operator--()
Prefix decrement operator.
Definition: persistent_ptr.hpp:194
persistent_ptr< T > & operator+=(std::ptrdiff_t s)
Addition assignment operator.
Definition: persistent_ptr.hpp:218
void flush(void)
Flushes what the persistent pointer points to.
Definition: persistent_ptr.hpp:285
void persist(const void *addr, size_t len) noexcept
Performs persist operation on a given chunk of memory.
Definition: pool.hpp:283
pmem::detail::sp_array_access< T >::type operator[](std::ptrdiff_t i) const noexcept
Array access operator.
Definition: persistent_ptr.hpp:156
static persistent_ptr< T > pointer_to(T &ref)
Create a persistent pointer from a given reference.
Definition: persistent_ptr.hpp:309
const PMEMoid & raw() const noexcept
Get PMEMoid encapsulated by this object.
Definition: persistent_ptr_base.hpp:304
pmem::detail::sp_dereference< T >::type operator*() const noexcept
Dereference operator.
Definition: persistent_ptr.hpp:134
Resides on pmem class.
Definition: p.hpp:64
T value_type
The type of the value pointed to by the persistent_ptr.
Definition: persistent_ptr.hpp:347
void flush(const void *addr, size_t len) noexcept
Performs flush operation on a given chunk of memory.
Definition: pool.hpp:319
Base class for persistent_ptr.
std::ptrdiff_t difference_type
The persistent_ptr difference type.
Definition: persistent_ptr.hpp:342
persistent_ptr(persistent_ptr< void > const &rhs) noexcept
Explicit void specialization of the converting constructor.
Definition: persistent_ptr.hpp:110
C++ pmemobj pool.
T & reference
The reference type of the value pointed to by the persistent_ptr.
Definition: persistent_ptr.hpp:352