4 #ifndef LIBPMEMOBJ_CPP_TAGGED_PTR
5 #define LIBPMEMOBJ_CPP_TAGGED_PTR
10 #include <libpmemobj++/experimental/atomic_self_relative_ptr.hpp>
19 template <
typename P1,
typename P2,
typename Po
interType>
20 struct tagged_ptr_impl {
21 tagged_ptr_impl() =
default;
22 tagged_ptr_impl(
const tagged_ptr_impl &rhs) =
default;
24 tagged_ptr_impl(std::nullptr_t) : ptr(nullptr)
29 tagged_ptr_impl(
const PointerType &ptr) : ptr(ptr)
33 tagged_ptr_impl(
const obj::persistent_ptr<P1> &ptr)
34 : ptr(add_tag(ptr.
get()))
36 assert(get<P1>() == ptr.get());
39 tagged_ptr_impl(
const obj::persistent_ptr<P2> &ptr) : ptr(ptr.
get())
41 assert(get<P2>() == ptr.get());
44 tagged_ptr_impl &operator=(
const tagged_ptr_impl &rhs) =
default;
46 tagged_ptr_impl &operator=(std::nullptr_t)
54 operator=(
const obj::persistent_ptr<P1> &rhs)
56 ptr = add_tag(rhs.get());
57 assert(get<P1>() == rhs.get());
62 operator=(
const obj::persistent_ptr<P2> &rhs)
65 assert(get<P2>() == rhs.get());
73 return ptr.to_byte_pointer() == rhs.ptr.to_byte_pointer();
78 return !(*
this == rhs);
84 return is_tagged() && get<P1>() == rhs;
90 return !(*
this == rhs);
94 swap(tagged_ptr_impl &rhs)
100 typename std::enable_if<std::is_same<T, P1>::value,
bool>::type
106 template <
typename T>
107 typename std::enable_if<!std::is_same<T, P1>::value,
bool>::type
113 template <
typename T>
114 typename std::enable_if<std::is_same<T, P1>::value, T *>::type
118 return static_cast<P1 *
>(remove_tag(ptr.to_void_pointer()));
121 template <
typename T>
122 typename std::enable_if<!std::is_same<T, P1>::value, T *>::type
125 assert(!is_tagged());
126 return static_cast<P2 *
>(ptr.to_void_pointer());
129 P2 *operator->()
const
134 explicit operator bool() const noexcept
136 return remove_tag(ptr.to_void_pointer()) !=
nullptr;
140 static constexpr uintptr_t IS_TAGGED = 1;
142 add_tag(P1 *ptr)
const
145 reinterpret_cast<uintptr_t
>(ptr) | uintptr_t(IS_TAGGED);
146 return reinterpret_cast<P1 *
>(tagged);
150 remove_tag(
void *ptr)
const
152 auto untagged =
reinterpret_cast<uintptr_t
>(ptr) &
153 ~uintptr_t(IS_TAGGED);
154 return reinterpret_cast<void *
>(untagged);
160 auto value =
reinterpret_cast<uintptr_t
>(ptr.to_void_pointer());
161 return value & uintptr_t(IS_TAGGED);
166 #ifndef DOXYGEN_SHOULD_SKIP_THIS
167 friend std::atomic<tagged_ptr_impl<
168 P1, P2, obj::experimental::self_relative_ptr<void>>>;
172 template <
typename P1,
typename P2>
174 tagged_ptr_impl<P1, P2, obj::experimental::self_relative_ptr<void>>;
182 template <
typename P1,
typename P2>
183 struct atomic<
pmem::detail::tagged_ptr<P1, P2>> {
185 using ptr_type = pmem::detail::tagged_ptr_impl<
187 atomic<pmem::obj::experimental::self_relative_ptr<void>>>;
188 using value_type = pmem::detail::tagged_ptr<P1, P2>;
194 constexpr atomic() noexcept = default;
196 atomic(value_type value) : ptr()
201 atomic(
const atomic &) =
delete;
204 store(value_type desired,
205 std::memory_order order = std::memory_order_seq_cst) noexcept
207 LIBPMEMOBJ_CPP_ANNOTATE_HAPPENS_BEFORE(order, &ptr.ptr);
208 ptr.ptr.store(desired.ptr, order);
212 store_with_snapshot(value_type desired,
213 std::memory_order order = std::memory_order_seq_cst)
215 LIBPMEMOBJ_CPP_ANNOTATE_HAPPENS_BEFORE(order, &ptr.ptr);
217 ptr.ptr.store(desired.ptr, order);
221 store_with_snapshot_release(value_type desired)
223 store_with_snapshot(desired, std::memory_order_release);
227 load(std::memory_order order = std::memory_order_seq_cst)
const noexcept
229 #if LIBPMEMOBJ_CPP_VG_HELGRIND_ENABLED
230 VALGRIND_HG_DISABLE_CHECKING(&ptr.ptr,
sizeof(ptr.ptr));
232 auto ret = this->ptr.ptr.load(order);
233 LIBPMEMOBJ_CPP_ANNOTATE_HAPPENS_AFTER(order, &ptr.ptr);
234 return value_type(ret);
238 load_acquire() const noexcept
240 return load(std::memory_order_acquire);
244 swap(atomic<pmem::detail::tagged_ptr<P1, P2>> &rhs)
246 auto tmp = rhs.load();
247 rhs.store_with_snapshot(this->load());
248 this->store_with_snapshot(tmp);
251 atomic<pmem::detail::tagged_ptr<P1, P2>> &
252 operator=(atomic<pmem::detail::tagged_ptr<P1, P2>> &) =
delete;
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:428
Commonly used functionality.
bool operator!=(const allocator< T, P, Tr > &lhs, const OtherAllocator &rhs)
Determines if memory from another allocator can be deallocated from this one.
Definition: allocator.hpp:536
T & get(pmem::obj::array< T, N > &a)
Non-member get function.
Definition: array.hpp:919
bool operator==(standard_alloc_policy< T > const &, standard_alloc_policy< T2 > const &)
Determines if memory from another allocator can be deallocated from this one.
Definition: allocator.hpp:420
void swap(pmem::obj::array< T, N > &lhs, pmem::obj::array< T, N > &rhs)
Non-member swap function.
Definition: array.hpp:909
Persistent memory namespace.
Definition: allocation_flag.hpp:15
Persistent smart pointer.
Persistent self-relative smart pointer.