9 #ifndef LIBPMEMOBJ_CPP_TAGGED_PTR
10 #define LIBPMEMOBJ_CPP_TAGGED_PTR
24 template <
typename P1,
typename P2,
typename Po
interType>
25 struct tagged_ptr_impl {
26 tagged_ptr_impl() =
default;
27 tagged_ptr_impl(
const tagged_ptr_impl &rhs) =
default;
29 tagged_ptr_impl(std::nullptr_t) : ptr(nullptr)
34 tagged_ptr_impl(
const PointerType &ptr) : ptr(ptr)
38 tagged_ptr_impl(
const obj::persistent_ptr<P1> &ptr)
39 : ptr(add_tag(ptr.get()))
41 assert(get<P1>() == ptr.get());
44 tagged_ptr_impl(
const obj::persistent_ptr<P2> &ptr) : ptr(ptr.get())
46 assert(get<P2>() == ptr.get());
49 tagged_ptr_impl &operator=(
const tagged_ptr_impl &rhs) =
default;
51 tagged_ptr_impl &operator=(std::nullptr_t)
59 operator=(
const obj::persistent_ptr<P1> &rhs)
61 ptr = add_tag(rhs.get());
62 assert(get<P1>() == rhs.get());
67 operator=(
const obj::persistent_ptr<P2> &rhs)
70 assert(get<P2>() == rhs.get());
76 operator==(
const tagged_ptr_impl &rhs)
const
78 return ptr.to_byte_pointer() == rhs.ptr.to_byte_pointer();
81 operator!=(
const tagged_ptr_impl &rhs)
const
83 return !(*
this == rhs);
87 operator==(
const P1 *rhs)
const
89 return is_tagged() && get<P1>() == rhs;
93 operator!=(
const P2 *rhs)
const
95 return !(*
this == rhs);
99 swap(tagged_ptr_impl &rhs)
104 template <
typename T>
105 typename std::enable_if<std::is_same<T, P1>::value,
bool>::type
111 template <
typename T>
112 typename std::enable_if<!std::is_same<T, P1>::value,
bool>::type
118 template <
typename T>
119 typename std::enable_if<std::is_same<T, P1>::value, T *>::type
123 return static_cast<P1 *
>(remove_tag(ptr.to_void_pointer()));
126 template <
typename T>
127 typename std::enable_if<!std::is_same<T, P1>::value, T *>::type
130 assert(!is_tagged());
131 return static_cast<P2 *
>(ptr.to_void_pointer());
134 P2 *operator->()
const
139 explicit operator bool() const noexcept
141 return remove_tag(ptr.to_void_pointer()) !=
nullptr;
145 static constexpr uintptr_t IS_TAGGED = 1;
147 add_tag(P1 *ptr)
const
150 reinterpret_cast<uintptr_t
>(ptr) | uintptr_t(IS_TAGGED);
151 return reinterpret_cast<P1 *
>(tagged);
155 remove_tag(
void *ptr)
const
157 auto untagged =
reinterpret_cast<uintptr_t
>(ptr) &
158 ~uintptr_t(IS_TAGGED);
159 return reinterpret_cast<void *
>(untagged);
165 auto value =
reinterpret_cast<uintptr_t
>(ptr.to_void_pointer());
166 return value & uintptr_t(IS_TAGGED);
171 friend struct std::atomic<tagged_ptr_impl<
172 P1, P2, obj::experimental::self_relative_ptr<void>>>;
175 template <typename P1, typename P2>
177 tagged_ptr_impl<P1, P2, obj::experimental::self_relative_ptr<void>>;
185 template <
typename P1,
typename P2>
186 struct atomic<
pmem::detail::tagged_ptr<P1, P2>> {
188 using ptr_type = pmem::detail::tagged_ptr_impl<
190 atomic<pmem::obj::experimental::self_relative_ptr<void>>>;
191 using value_type = pmem::detail::tagged_ptr<P1, P2>;
197 constexpr atomic() noexcept = default;
199 atomic(value_type value) : ptr()
204 atomic(
const atomic &) =
delete;
207 store(value_type desired,
208 std::memory_order order = std::memory_order_seq_cst) noexcept
210 LIBPMEMOBJ_CPP_ANNOTATE_HAPPENS_BEFORE(order, &ptr.ptr);
211 ptr.ptr.store(desired.ptr, order);
215 store_with_snapshot(value_type desired,
216 std::memory_order order = std::memory_order_seq_cst)
218 LIBPMEMOBJ_CPP_ANNOTATE_HAPPENS_BEFORE(order, &ptr.ptr);
220 ptr.ptr.store(desired.ptr, order);
224 store_with_snapshot_release(value_type desired)
226 store_with_snapshot(desired, std::memory_order_release);
230 load(std::memory_order order = std::memory_order_seq_cst)
const noexcept
232 #if LIBPMEMOBJ_CPP_VG_HELGRIND_ENABLED
233 VALGRIND_HG_DISABLE_CHECKING(&ptr.ptr,
sizeof(ptr.ptr));
235 auto ret = this->ptr.ptr.load(order);
236 LIBPMEMOBJ_CPP_ANNOTATE_HAPPENS_AFTER(order, &ptr.ptr);
237 return value_type(ret);
241 load_acquire() const noexcept
243 return load(std::memory_order_acquire);
247 swap(atomic<pmem::detail::tagged_ptr<P1, P2>> &rhs)
249 auto tmp = rhs.load();
250 rhs.store_with_snapshot(this->load());
251 this->store_with_snapshot(tmp);
254 atomic<pmem::detail::tagged_ptr<P1, P2>> &
255 operator=(atomic<pmem::detail::tagged_ptr<P1, P2>> &) =
delete;
Atomic specialization for self_relative_ptr.
static void snapshot(const T *addr, size_t num=1)
Takes a “snapshot” of given elements of type T number (1 by default), located at the given address pt...
Definition: transaction.hpp:437
Commonly used functionality.
Persistent memory namespace.
Definition: allocation_flag.hpp:15
Persistent smart pointer.
Persistent self-relative smart pointer.