NVML C++ bindings  0.1 experimental
This is the C++ bindings documentation for NVML's libpmemobj.
persistent_ptr.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 2015-2016, 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 PMEMOBJ_PERSISTENT_PTR_HPP
39 #define PMEMOBJ_PERSISTENT_PTR_HPP
40 
41 #include <cassert>
42 #include <memory>
43 #include <ostream>
44 
47 #include "libpmemobj++/pool.hpp"
48 
49 namespace nvml
50 {
51 
52 namespace obj
53 {
54 template <typename T>
55 class pool;
56 
71 template <typename T>
73  template <typename Y>
74  friend class persistent_ptr;
75 
77 
78 public:
83  typedef typename nvml::detail::sp_element<T>::type element_type;
84 
88  persistent_ptr() : oid(OID_NULL)
89  {
90  verify_type();
91  }
92 
93  /*
94  * Curly braces initialization is not used because the
95  * PMEMoid is a plain C (POD) type and we can't add a default
96  * constructor in there.
97  */
98 
102  persistent_ptr(std::nullptr_t) noexcept : oid(OID_NULL)
103  {
104  verify_type();
105  }
106 
114  persistent_ptr(PMEMoid oid) noexcept : oid(oid)
115  {
116  verify_type();
117  }
118 
125  template <typename Y,
126  typename = typename std::enable_if<
127  std::is_convertible<Y *, T *>::value>::type>
128  persistent_ptr(const persistent_ptr<Y> &r) noexcept : oid(r.oid)
129  {
130  verify_type();
131  }
132 
133  /*
134  * Copy constructor.
135  *
136  * @param r Persistent pointer to the same type.
137  */
138  persistent_ptr(const persistent_ptr &r) noexcept : oid(r.oid)
139  {
140  verify_type();
141  }
142 
146  persistent_ptr(persistent_ptr &&r) noexcept : oid(std::move(r.oid))
147  {
148  verify_type();
149  }
150 
156  {
157  detail::conditional_add_to_tx(this);
158  this->oid = std::move(r.oid);
159 
160  return *this;
161  }
162 
175  {
176  detail::conditional_add_to_tx(this);
177  this_type(r).swap(*this);
178 
179  return *this;
180  }
181 
193  template <typename Y,
194  typename = typename std::enable_if<
195  std::is_convertible<Y *, T *>::value>::type>
198  {
199  detail::conditional_add_to_tx(this);
200  this_type(r).swap(*this);
201 
202  return *this;
203  }
204 
208  typename nvml::detail::sp_dereference<T>::type operator*() const
209  noexcept
210  {
211  return *get();
212  }
213 
217  typename nvml::detail::sp_member_access<T>::type operator->() const
218  noexcept
219  {
220  return get();
221  }
222 
228  typename nvml::detail::sp_array_access<T>::type
229  operator[](std::ptrdiff_t i) const noexcept
230  {
231  assert(i >= 0 && (i < nvml::detail::sp_extent<T>::value ||
232  nvml::detail::sp_extent<T>::value == 0) &&
233  "persistent array index out of bounds");
234 
235  return get()[i];
236  }
237 
245  element_type *
246  get() const noexcept
247  {
248  return (element_type *)pmemobj_direct(this->oid);
249  }
250 
254  void
255  swap(persistent_ptr &other) noexcept
256  {
257  std::swap(this->oid, other.oid);
258  }
259 
260  /*
261  * Bool conversion operator.
262  */
263  explicit operator bool() const noexcept
264  {
265  return get() != nullptr;
266  }
267 
275  const PMEMoid &
276  raw() const noexcept
277  {
278  return this->oid;
279  }
280 
288  PMEMoid *
289  raw_ptr() noexcept
290  {
291  return &(this->oid);
292  }
293 
298  {
299  detail::conditional_add_to_tx(this);
300  this->oid.off += sizeof(T);
301 
302  return *this;
303  }
304 
309  {
310  PMEMoid noid = this->oid;
311  ++(*this);
312 
313  return persistent_ptr<T>(noid);
314  }
315 
320  {
321  detail::conditional_add_to_tx(this);
322  this->oid.off -= sizeof(T);
323 
324  return *this;
325  }
326 
331  {
332  PMEMoid noid = this->oid;
333  --(*this);
334 
335  return persistent_ptr<T>(noid);
336  }
337 
341  inline persistent_ptr<T> &
342  operator+=(std::ptrdiff_t s)
343  {
344  detail::conditional_add_to_tx(this);
345  this->oid.off += s * sizeof(T);
346 
347  return *this;
348  }
349 
353  inline persistent_ptr<T> &
354  operator-=(std::ptrdiff_t s)
355  {
356  detail::conditional_add_to_tx(this);
357  this->oid.off -= s * sizeof(T);
358 
359  return *this;
360  }
361 
367  void
369  {
370  pop.persist(this->get(), sizeof(T));
371  }
372 
379  void
380  persist(void)
381  {
382  pmemobjpool *pop = pmemobj_pool_by_oid(this->raw());
383 
384  if (pop == nullptr)
385  throw pool_error("Cannot get pool from "
386  "persistent pointer");
387 
388  pmemobj_persist(pop, this->get(), sizeof(T));
389  }
390 
396  void
398  {
399  pop.flush(this->get(), sizeof(T));
400  }
401 
408  void
409  flush(void)
410  {
411  pmemobjpool *pop = pmemobj_pool_by_oid(this->raw());
412 
413  if (pop == nullptr)
414  throw pool_error("Cannot get pool from "
415  "persistent pointer");
416 
417  pmemobj_flush(pop, this->get(), sizeof(T));
418  }
419 
420 private:
421  /* The underlying PMEMoid of the held object. */
422  PMEMoid oid;
423 
424  /*
425  * C++ persistent memory support has following type limitations:
426  * en.cppreference.com/w/cpp/types/is_polymorphic
427  * en.cppreference.com/w/cpp/types/is_default_constructible
428  * en.cppreference.com/w/cpp/types/is_destructible
429  */
430  void
431  verify_type()
432  {
433  static_assert(!std::is_polymorphic<element_type>::value,
434  "Polymorphic types are not supported");
435  }
436 };
437 
444 template <class T>
445 inline void
447 {
448  a.swap(b);
449 }
450 
456 template <typename T, typename Y>
457 inline bool
458 operator==(const persistent_ptr<T> &lhs, const persistent_ptr<Y> &rhs) noexcept
459 {
460  return OID_EQUALS(lhs.raw(), rhs.raw());
461 }
462 
466 template <typename T, typename Y>
467 inline bool
468 operator!=(const persistent_ptr<T> &lhs, const persistent_ptr<Y> &rhs) noexcept
469 {
470  return !(lhs == rhs);
471 }
472 
476 template <typename T>
477 inline bool
478 operator==(const persistent_ptr<T> &lhs, std::nullptr_t) noexcept
479 {
480  return lhs.get() == nullptr;
481 }
482 
486 template <typename T>
487 inline bool
488 operator==(std::nullptr_t, const persistent_ptr<T> &lhs) noexcept
489 {
490  return lhs.get() == nullptr;
491 }
492 
496 template <typename T>
497 inline bool
498 operator!=(const persistent_ptr<T> &lhs, std::nullptr_t) noexcept
499 {
500  return lhs.get() != nullptr;
501 }
502 
506 template <typename T>
507 inline bool
508 operator!=(std::nullptr_t, const persistent_ptr<T> &lhs) noexcept
509 {
510  return lhs.get() != nullptr;
511 }
512 
520 template <typename T, typename Y>
521 inline bool
522 operator<(const persistent_ptr<T> &lhs, const persistent_ptr<Y> &rhs) noexcept
523 {
524  if (lhs.raw().pool_uuid_lo == rhs.raw().pool_uuid_lo)
525  return lhs.raw().off < rhs.raw().off;
526  else
527  return lhs.raw().pool_uuid_lo < rhs.raw().pool_uuid_lo;
528 }
529 
535 template <typename T, typename Y>
536 inline bool
537 operator<=(const persistent_ptr<T> &lhs, const persistent_ptr<Y> &rhs) noexcept
538 {
539  return !(rhs < lhs);
540 }
541 
547 template <typename T, typename Y>
548 inline bool
549 operator>(const persistent_ptr<T> &lhs, const persistent_ptr<Y> &rhs) noexcept
550 {
551  return (rhs < lhs);
552 }
553 
559 template <typename T, typename Y>
560 inline bool
561 operator>=(const persistent_ptr<T> &lhs, const persistent_ptr<Y> &rhs) noexcept
562 {
563  return !(lhs < rhs);
564 }
565 
566 /* nullptr comparisons */
567 
571 template <typename T>
572 inline bool
573 operator<(const persistent_ptr<T> &lhs, std::nullptr_t) noexcept
574 {
575  return std::less<typename persistent_ptr<T>::element_type *>()(
576  lhs.get(), nullptr);
577 }
578 
582 template <typename T>
583 inline bool
584 operator<(std::nullptr_t, const persistent_ptr<T> &rhs) noexcept
585 {
586  return std::less<typename persistent_ptr<T>::element_type *>()(
587  nullptr, rhs.get());
588 }
589 
593 template <typename T>
594 inline bool
595 operator<=(const persistent_ptr<T> &lhs, std::nullptr_t) noexcept
596 {
597  return !(nullptr < lhs);
598 }
599 
603 template <typename T>
604 inline bool
605 operator<=(std::nullptr_t, const persistent_ptr<T> &rhs) noexcept
606 {
607  return !(rhs < nullptr);
608 }
609 
613 template <typename T>
614 inline bool
615 operator>(const persistent_ptr<T> &lhs, std::nullptr_t) noexcept
616 {
617  return nullptr < lhs;
618 }
619 
623 template <typename T>
624 inline bool
625 operator>(std::nullptr_t, const persistent_ptr<T> &rhs) noexcept
626 {
627  return rhs < nullptr;
628 }
629 
633 template <typename T>
634 inline bool
635 operator>=(const persistent_ptr<T> &lhs, std::nullptr_t) noexcept
636 {
637  return !(lhs < nullptr);
638 }
639 
643 template <typename T>
644 inline bool
645 operator>=(std::nullptr_t, const persistent_ptr<T> &rhs) noexcept
646 {
647  return !(nullptr < rhs);
648 }
649 
653 template <typename T>
654 inline persistent_ptr<T>
655 operator+(const persistent_ptr<T> &lhs, std::ptrdiff_t s)
656 {
657  PMEMoid noid;
658  noid.pool_uuid_lo = lhs.raw().pool_uuid_lo;
659  noid.off = lhs.raw().off + (s * sizeof(T));
660  return persistent_ptr<T>(noid);
661 }
662 
666 template <typename T>
667 inline persistent_ptr<T>
668 operator-(const persistent_ptr<T> &lhs, std::ptrdiff_t s)
669 {
670  PMEMoid noid;
671  noid.pool_uuid_lo = lhs.raw().pool_uuid_lo;
672  noid.off = lhs.raw().off - (s * sizeof(T));
673  return persistent_ptr<T>(noid);
674 }
675 
683 template <typename T>
684 inline ptrdiff_t
686 {
687  assert(lhs.raw().pool_uuid_lo == rhs.raw().pool_uuid_lo);
688  ptrdiff_t d = lhs.raw().off - rhs.raw().off;
689 
690  return d / sizeof(T);
691 }
692 
696 template <typename T>
697 std::ostream &
698 operator<<(std::ostream &os, const persistent_ptr<T> &pptr)
699 {
700  PMEMoid raw_oid = pptr.raw();
701  os << std::hex << "0x" << raw_oid.pool_uuid_lo << ", 0x" << raw_oid.off
702  << std::dec;
703  return os;
704 }
705 
706 } /* namespace obj */
707 
708 } /* namespace nvml */
709 
710 #endif /* PMEMOBJ_PERSISTENT_PTR_HPP */
void swap(persistent_ptr &other) noexcept
Swaps two persistent_ptr objects of the same type.
Definition: persistent_ptr.hpp:255
Persistent pointer class.
Definition: persistent_ptr.hpp:72
PMEMoid * raw_ptr() noexcept
Get pointer to PMEMoid encapsulated by this object.
Definition: persistent_ptr.hpp:289
Helper template for persistent ptr specialization.
persistent_ptr< T > operator-(const persistent_ptr< T > &lhs, std::ptrdiff_t s)
Subtraction operator for persistent pointers.
Definition: persistent_ptr.hpp:668
bool operator>=(const persistent_ptr< T > &lhs, const persistent_ptr< Y > &rhs) noexcept
Greater or equal than operator.
Definition: persistent_ptr.hpp:561
persistent_ptr(persistent_ptr &&r) noexcept
Defaulted move constructor.
Definition: persistent_ptr.hpp:146
nvml::detail::sp_element< T >::type element_type
Type of an actual object with all qualifier removed, used for easy underlying type access...
Definition: persistent_ptr.hpp:83
persistent_ptr< T > & operator--()
Prefix decrement operator.
Definition: persistent_ptr.hpp:319
The non-template pool base class.
Definition: pool.hpp:64
nvml::detail::sp_member_access< T >::type operator->() const noexcept
Member access operator.
Definition: persistent_ptr.hpp:217
bool operator==(const persistent_ptr< T > &lhs, const persistent_ptr< Y > &rhs) noexcept
Equality operator.
Definition: persistent_ptr.hpp:458
nvml::detail::sp_dereference< T >::type operator*() const noexcept
Dereference operator.
Definition: persistent_ptr.hpp:208
persistent_ptr()
Default constructor, zeroes the PMEMoid.
Definition: persistent_ptr.hpp:88
persistent_ptr< T > operator++(int)
Postfix increment operator.
Definition: persistent_ptr.hpp:308
persistent_ptr< T > operator+(const persistent_ptr< T > &lhs, std::ptrdiff_t s)
Addition operator for persistent pointers.
Definition: persistent_ptr.hpp:655
Commonly used functionality.
void persist(pool_base &pop)
Persists the content of the underlying object.
Definition: persistent_ptr.hpp:368
persistent_ptr< T > & operator-=(std::ptrdiff_t s)
Subtraction assignment operator.
Definition: persistent_ptr.hpp:354
persistent_ptr(PMEMoid oid) noexcept
PMEMoid constructor.
Definition: persistent_ptr.hpp:114
persistent_ptr< T > operator--(int)
Postfix decrement operator.
Definition: persistent_ptr.hpp:330
const PMEMoid & raw() const noexcept
Get PMEMoid encapsulated by this object.
Definition: persistent_ptr.hpp:276
persistent_ptr(std::nullptr_t) noexcept
Default null constructor, zeroes the PMEMoid.
Definition: persistent_ptr.hpp:102
bool operator>(const persistent_ptr< T > &lhs, const persistent_ptr< Y > &rhs) noexcept
Greater than operator.
Definition: persistent_ptr.hpp:549
persistent_ptr< T > & operator++()
Prefix increment operator.
Definition: persistent_ptr.hpp:297
PMEMobj pool class.
Definition: persistent_ptr.hpp:55
persistent_ptr(const persistent_ptr< Y > &r) noexcept
Copy constructor from a different persistent_ptr<>.
Definition: persistent_ptr.hpp:128
persistent_ptr< T > & operator+=(std::ptrdiff_t s)
Addition assignment operator.
Definition: persistent_ptr.hpp:342
void flush(const void *addr, size_t len) noexcept
Performs flush operation on a given chunk of memory.
Definition: pool.hpp:234
void flush(pool_base &pop)
Flushes what the persistent pointer points to.
Definition: persistent_ptr.hpp:397
bool operator!=(const persistent_ptr< T > &lhs, const persistent_ptr< Y > &rhs) noexcept
Inequality operator.
Definition: persistent_ptr.hpp:468
void persist(const void *addr, size_t len) noexcept
Performs persist operation on a given chunk of memory.
Definition: pool.hpp:198
persistent_ptr & operator=(const persistent_ptr &r)
Assignment operator.
Definition: persistent_ptr.hpp:174
Definition: condition_variable.hpp:48
persistent_ptr & operator=(const persistent_ptr< Y > &r)
Converting assignment operator from a different persistent_ptr<>.
Definition: persistent_ptr.hpp:197
void flush(void)
Flushes what the persistent pointer points to.
Definition: persistent_ptr.hpp:409
void persist(void)
Persists what the persistent pointer points to.
Definition: persistent_ptr.hpp:380
persistent_ptr & operator=(persistent_ptr &&r)
Defaulted move assignment operator.
Definition: persistent_ptr.hpp:155
nvml::detail::sp_array_access< T >::type operator[](std::ptrdiff_t i) const noexcept
Array access operator.
Definition: persistent_ptr.hpp:229
element_type * get() const noexcept
Get a direct pointer.
Definition: persistent_ptr.hpp:246
C++ pmemobj pool.
Custom pool error class.
Definition: pexceptions.hpp:53