persistent_ptr_base.hpp
/*
* Copyright 2016-2017, Intel Corporation
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef PMEMOBJ_PERSISTENT_PTR_BASE_HPP
#define PMEMOBJ_PERSISTENT_PTR_BASE_HPP
#include <type_traits>
#include "libpmemobj++/detail/common.hpp"
#include "libpmemobj++/detail/specialization.hpp"
#include "libpmemobj.h"
/* Windows has a max macro which collides with std::numeric_limits::max */
#if defined(max) && defined(_WIN32)
#undef max
#endif
namespace pmem
{
namespace detail
{
template <typename T>
class persistent_ptr_base {
typedef persistent_ptr_base<T> this_type;
template <typename U>
friend class persistent_ptr_base;
public:
typedef typename pmem::detail::sp_element<T>::type element_type;
persistent_ptr_base() : oid(OID_NULL)
{
verify_type();
}
/*
* Curly braces initialization is not used because the
* PMEMoid is a plain C (POD) type and we can't add a default
* constructor in there.
*/
persistent_ptr_base(PMEMoid oid) noexcept : oid(oid)
{
verify_type();
}
persistent_ptr_base(element_type *ptr) : oid(pmemobj_oid(ptr))
{
verify_type();
}
template <typename U,
typename = typename std::enable_if<
!std::is_same<T, U>::value &&
std::is_same<typename std::remove_cv<T>::type,
U>::value>::type>
persistent_ptr_base(persistent_ptr_base<U> const &r) noexcept
: oid(r.oid)
{
this->oid.off += calculate_offset<U>();
verify_type();
}
template <
typename U, typename Dummy = void,
typename = typename std::enable_if<
!std::is_same<
typename std::remove_cv<T>::type,
typename std::remove_cv<U>::type>::value &&
!std::is_void<U>::value,
decltype(static_cast<T *>(std::declval<U *>()))>::type>
persistent_ptr_base(persistent_ptr_base<U> const &r) noexcept
: oid(r.oid)
{
this->oid.off += calculate_offset<U>();
verify_type();
}
template <
typename Y,
typename = typename std::enable_if<
!std::is_same<
typename std::remove_cv<T>::type,
typename std::remove_cv<Y>::type>::value &&
!std::is_void<Y>::value,
decltype(static_cast<T *>(std::declval<Y *>()))>::type>
operator persistent_ptr_base<Y>() noexcept
{
/*
* The offset conversion should not be required here.
*/
return persistent_ptr_base<Y>(this->oid);
}
/*
* Copy constructor.
*
* @param r Persistent pointer to the same type.
*/
persistent_ptr_base(persistent_ptr_base const &r) noexcept : oid(r.oid)
{
verify_type();
}
persistent_ptr_base(persistent_ptr_base &&r) noexcept
: oid(std::move(r.oid))
{
verify_type();
}
persistent_ptr_base &
operator=(persistent_ptr_base &&r)
{
detail::conditional_add_to_tx(this);
this->oid = std::move(r.oid);
return *this;
}
persistent_ptr_base &
operator=(persistent_ptr_base const &r)
{
this_type(r).swap(*this);
return *this;
}
persistent_ptr_base &
operator=(std::nullptr_t &&)
{
detail::conditional_add_to_tx(this);
this->oid = {0, 0};
return *this;
}
template <typename Y,
typename = typename std::enable_if<
std::is_convertible<Y *, T *>::value>::type>
persistent_ptr_base &
operator=(persistent_ptr_base<Y> const &r)
{
this_type(r).swap(*this);
return *this;
}
void
swap(persistent_ptr_base &other)
{
detail::conditional_add_to_tx(this);
detail::conditional_add_to_tx(&other);
std::swap(this->oid, other.oid);
}
element_type *
get() const noexcept
{
if (this->oid.pool_uuid_lo ==
std::numeric_limits<decltype(oid.pool_uuid_lo)>::max())
return reinterpret_cast<element_type *>(oid.off);
else
return static_cast<element_type *>(
pmemobj_direct(this->oid));
}
const PMEMoid &
raw() const noexcept
{
return this->oid;
}
PMEMoid *
raw_ptr() noexcept
{
return &(this->oid);
}
/*
* Bool conversion operator.
*/
explicit operator bool() const noexcept
{
return get() != nullptr;
}
protected:
/* The underlying PMEMoid of the held object. */
PMEMoid oid;
/*
* C++ persistent memory support has following type limitations:
* en.cppreference.com/w/cpp/types/is_polymorphic
* en.cppreference.com/w/cpp/types/is_default_constructible
* en.cppreference.com/w/cpp/types/is_destructible
*/
void
verify_type()
{
static_assert(!std::is_polymorphic<element_type>::value,
"Polymorphic types are not supported");
}
persistent_ptr_base(element_type *vptr, int) : persistent_ptr_base(vptr)
{
if (OID_IS_NULL(oid)) {
oid.pool_uuid_lo = std::numeric_limits<decltype(
oid.pool_uuid_lo)>::max();
oid.off = reinterpret_cast<decltype(oid.off)>(vptr);
}
}
template <typename U>
inline ptrdiff_t
calculate_offset() const
{
static const ptrdiff_t ptr_offset_magic = 0xDEADBEEF;
U *tmp{reinterpret_cast<U *>(ptr_offset_magic)};
T *diff = static_cast<T *>(tmp);
return reinterpret_cast<ptrdiff_t>(diff) -
reinterpret_cast<ptrdiff_t>(tmp);
}
};
} /* namespace detail */
} /* namespace pmem */
#endif /* PMEMOBJ_PERSISTENT_PTR_BASE_HPP */
pmem::detail::persistent_ptr_base
Persistent_ptr base class.
Definition: persistent_ptr_base.hpp:62
pmem::detail::persistent_ptr_base::operator=
persistent_ptr_base & operator=(persistent_ptr_base &&r)
Defaulted move assignment operator.
Definition: persistent_ptr_base.hpp:195
specialization.hpp
Helper template for persistent ptr specialization.
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:124
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:250
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:73
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:263
pmem::detail::persistent_ptr_base::operator=
persistent_ptr_base & operator=(std::nullptr_t &&)
Nullptr move assignment operator.
Definition: persistent_ptr_base.hpp:228
pmem::detail::persistent_ptr_base::persistent_ptr_base
persistent_ptr_base(persistent_ptr_base &&r) noexcept
Defaulted move constructor.
Definition: persistent_ptr_base.hpp:185
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:144
common.hpp
Commonly used functionality.
pmem::detail::persistent_ptr_base::persistent_ptr_base
persistent_ptr_base(element_type *ptr)
Volatile pointer constructor.
Definition: persistent_ptr_base.hpp:109
pmem::detail::persistent_ptr_base::persistent_ptr_base
persistent_ptr_base()
Default constructor, zeroes the PMEMoid.
Definition: persistent_ptr_base.hpp:78
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:371
pmem::detail::persistent_ptr_base::operator=
persistent_ptr_base & operator=(persistent_ptr_base const &r)
Assignment operator.
Definition: persistent_ptr_base.hpp:214
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:346
pmem::detail::persistent_ptr_base::raw
const PMEMoid & raw() const noexcept
Get PMEMoid encapsulated by this object.
Definition: persistent_ptr_base.hpp:296
pmem::detail::persistent_ptr_base::raw_ptr
PMEMoid * raw_ptr() noexcept
Get pointer to PMEMoid encapsulated by this object.
Definition: persistent_ptr_base.hpp:309
pmem::detail::persistent_ptr_base::persistent_ptr_base
persistent_ptr_base(PMEMoid oid) noexcept
PMEMoid constructor.
Definition: persistent_ptr_base.hpp:96
pmem
Definition: allocator.hpp:48