PMDK C++ bindings  1.6.1
This is the C++ bindings documentation for PMDK's libpmemobj.
persistent_ptr_base.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 2016-2021, 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_BASE_HPP
39 #define LIBPMEMOBJ_CPP_PERSISTENT_PTR_BASE_HPP
40 
41 #include <cstdint>
42 #include <type_traits>
43 
46 #include <libpmemobj.h>
47 
48 /* Windows has a max macro which collides with std::numeric_limits::max */
49 #if defined(max) && defined(_WIN32)
50 #undef max
51 #endif
52 
53 namespace pmem
54 {
55 
56 namespace detail
57 {
58 
67 template <typename T>
70 
71  template <typename U>
72  friend class persistent_ptr_base;
73 
74 public:
79  typedef typename pmem::detail::sp_element<T>::type element_type;
80 
84  persistent_ptr_base() : oid(OID_NULL)
85  {
86  verify_type();
87  }
88 
89  /*
90  * Curly braces initialization is not used because the
91  * PMEMoid is a plain C (POD) type and we can't add a default
92  * constructor in there.
93  */
94 
102  persistent_ptr_base(PMEMoid oid) noexcept : oid(oid)
103  {
104  verify_type();
105  }
106 
115  persistent_ptr_base(element_type *ptr) : oid(pmemobj_oid(ptr))
116  {
117  verify_type();
118  }
119 
125  template <typename U,
126  typename = typename std::enable_if<
127  !std::is_same<T, U>::value &&
128  std::is_same<typename std::remove_cv<T>::type,
129  U>::value>::type>
131  : oid(r.oid)
132  {
133  this->oid.off +=
134  static_cast<std::uint64_t>(calculate_offset<U>());
135  verify_type();
136  }
137 
143  template <
144  typename U, typename Dummy = void,
145  typename = typename std::enable_if<
146  !std::is_same<
147  typename std::remove_cv<T>::type,
148  typename std::remove_cv<U>::type>::value &&
149  !std::is_void<U>::value,
150  decltype(static_cast<T *>(std::declval<U *>()))>::type>
152  : oid(r.oid)
153  {
154  this->oid.off +=
155  static_cast<std::uint64_t>(calculate_offset<U>());
156  verify_type();
157  }
158 
164  template <
165  typename Y,
166  typename = typename std::enable_if<
167  !std::is_same<
168  typename std::remove_cv<T>::type,
169  typename std::remove_cv<Y>::type>::value &&
170  !std::is_void<Y>::value,
171  decltype(static_cast<T *>(std::declval<Y *>()))>::type>
172  operator persistent_ptr_base<Y>() noexcept
173  {
174  /*
175  * The offset conversion should not be required here.
176  */
177  return persistent_ptr_base<Y>(this->oid);
178  }
179 
180  /*
181  * Copy constructor.
182  *
183  * @param r Persistent pointer to the same type.
184  */
185  persistent_ptr_base(persistent_ptr_base const &r) noexcept : oid(r.oid)
186  {
187  verify_type();
188  }
189 
194  : oid(std::move(r.oid))
195  {
196  verify_type();
197  }
198 
204  {
205  detail::conditional_add_to_tx(this);
206  this->oid = std::move(r.oid);
207 
208  return *this;
209  }
210 
223  {
224  this_type(r).swap(*this);
225 
226  return *this;
227  }
228 
236  operator=(std::nullptr_t &&)
237  {
238  detail::conditional_add_to_tx(this);
239  this->oid = {0, 0};
240  return *this;
241  }
242 
254  template <typename Y,
255  typename = typename std::enable_if<
256  std::is_convertible<Y *, T *>::value>::type>
259  {
260  this_type(r).swap(*this);
261 
262  return *this;
263  }
264 
270  void
272  {
273  detail::conditional_add_to_tx(this);
274  detail::conditional_add_to_tx(&other);
275  std::swap(this->oid, other.oid);
276  }
277 
285  element_type *
286  get() const noexcept
287  {
288  if (this->oid.pool_uuid_lo ==
289  std::numeric_limits<decltype(oid.pool_uuid_lo)>::max())
290  return reinterpret_cast<element_type *>(oid.off);
291  else
292  return static_cast<element_type *>(
293  pmemobj_direct(this->oid));
294  }
295 
303  const PMEMoid &
304  raw() const noexcept
305  {
306  return this->oid;
307  }
308 
316  PMEMoid *
317  raw_ptr() noexcept
318  {
319  return &(this->oid);
320  }
321 
322  /*
323  * Bool conversion operator.
324  */
325  explicit operator bool() const noexcept
326  {
327  return get() != nullptr;
328  }
329 
330 protected:
331  /* The underlying PMEMoid of the held object. */
332  PMEMoid oid;
333 
334  void
335  verify_type()
336  {
337  static_assert(!std::is_polymorphic<element_type>::value,
338  "Polymorphic types are not supported");
339  }
340 
349  {
350  if (OID_IS_NULL(oid)) {
351  oid.pool_uuid_lo = std::numeric_limits<decltype(
352  oid.pool_uuid_lo)>::max();
353  oid.off = reinterpret_cast<decltype(oid.off)>(vptr);
354  }
355  }
356 
371  template <typename U>
372  inline ptrdiff_t
374  {
375  static const ptrdiff_t ptr_offset_magic = 0xF00000000000000;
376 
377  static_assert(ptr_offset_magic % alignof(U) == 0, "");
378  static_assert(ptr_offset_magic % alignof(T) == 0, "");
379 
380  U *tmp{reinterpret_cast<U *>(ptr_offset_magic)};
381  T *diff = static_cast<T *>(tmp);
382  return reinterpret_cast<ptrdiff_t>(diff) -
383  reinterpret_cast<ptrdiff_t>(tmp);
384  }
385 };
386 
387 } /* namespace detail */
388 
389 } /* namespace pmem */
390 
391 #endif /* LIBPMEMOBJ_CPP_PERSISTENT_PTR_BASE_HPP */
pmem::detail::persistent_ptr_base
Persistent_ptr base class.
Definition: persistent_ptr_base.hpp:68
pmem::detail::persistent_ptr_base::get
element_type * get() const noexcept
Get a direct pointer.
Definition: persistent_ptr_base.hpp:286
pmem::detail::persistent_ptr_base::persistent_ptr_base
persistent_ptr_base(persistent_ptr_base< U > const &r) noexcept
Copy constructor from a different persistent_ptr<>.
Definition: persistent_ptr_base.hpp:151
pmem::detail::persistent_ptr_base::raw
const PMEMoid & raw() const noexcept
Get PMEMoid encapsulated by this object.
Definition: persistent_ptr_base.hpp:304
common.hpp
Commonly used functionality.
pmem::detail::persistent_ptr_base::element_type
pmem::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_base.hpp:79
pmem::detail::persistent_ptr_base::persistent_ptr_base
persistent_ptr_base(persistent_ptr_base< U > const &r) noexcept
Copy constructor from a different persistent_ptr<>.
Definition: persistent_ptr_base.hpp:130
pmem::detail::persistent_ptr_base::operator=
persistent_ptr_base & operator=(std::nullptr_t &&)
Nullptr move assignment operator.
Definition: persistent_ptr_base.hpp:236
pmem::detail::persistent_ptr_base::persistent_ptr_base
persistent_ptr_base(persistent_ptr_base &&r) noexcept
Defaulted move constructor.
Definition: persistent_ptr_base.hpp:193
pmem::detail::persistent_ptr_base::operator=
persistent_ptr_base & operator=(persistent_ptr_base const &r)
Assignment operator.
Definition: persistent_ptr_base.hpp:222
pmem::detail::persistent_ptr_base::operator=
persistent_ptr_base & operator=(persistent_ptr_base< Y > const &r)
Converting assignment operator from a different persistent_ptr<>.
Definition: persistent_ptr_base.hpp:258
specialization.hpp
Helper template for persistent ptr specialization.
pmem::detail::persistent_ptr_base::raw_ptr
PMEMoid * raw_ptr() noexcept
Get pointer to PMEMoid encapsulated by this object.
Definition: persistent_ptr_base.hpp:317
pmem::detail::persistent_ptr_base::persistent_ptr_base
persistent_ptr_base(PMEMoid oid) noexcept
PMEMoid constructor.
Definition: persistent_ptr_base.hpp:102
pmem::detail::persistent_ptr_base::persistent_ptr_base
persistent_ptr_base()
Default constructor, zeroes the PMEMoid.
Definition: persistent_ptr_base.hpp:84
pmem::detail::persistent_ptr_base::swap
void swap(persistent_ptr_base &other)
Swaps two persistent_ptr objects of the same type.
Definition: persistent_ptr_base.hpp:271
pmem::detail::persistent_ptr_base::persistent_ptr_base
persistent_ptr_base(element_type *vptr, int)
Private constructor enabling persistent_ptrs to volatile objects.
Definition: persistent_ptr_base.hpp:348
pmem::detail::persistent_ptr_base::operator=
persistent_ptr_base & operator=(persistent_ptr_base &&r)
Defaulted move assignment operator.
Definition: persistent_ptr_base.hpp:203
pmem::detail::persistent_ptr_base::persistent_ptr_base
persistent_ptr_base(element_type *ptr)
Volatile pointer constructor.
Definition: persistent_ptr_base.hpp:115
pmem::detail::persistent_ptr_base::calculate_offset
ptrdiff_t calculate_offset() const
Calculate in-object offset for structures with inheritance.
Definition: persistent_ptr_base.hpp:373