21 #include <glog/logging.h> 43 template <
typename T,
template <
typename>
class Atom>
51 auto p = link_.load(std::memory_order_relaxed);
90 template <
template <
typename>
class Atom>
94 static constexpr
Count kRef = 1u;
95 static constexpr
Count kLink = 1u << 16;
96 static constexpr
Count kRefMask = kLink - 1u;
97 static constexpr
Count kLinkMask = ~kRefMask;
99 Atom<Count> count_{0};
107 count_inc_safe(kLink);
115 count_inc_safe(kRef);
119 template <
typename,
template <
typename>
class,
typename>
123 return count_.load(std::memory_order_acquire);
127 count_.store(
val, std::memory_order_release);
131 auto oldval = count_.fetch_add(
add, std::memory_order_acq_rel);
132 DCHECK_LT(oldval & kLinkMask, kLinkMask);
133 DCHECK_LT(oldval & kRefMask, kRefMask);
137 auto oldval =
count();
138 count_set(oldval +
add);
139 DCHECK_LT(oldval & kLinkMask, kLinkMask);
140 DCHECK_LT(oldval & kRefMask, kRefMask);
144 return count_.compare_exchange_weak(
145 oldval, newval, std::memory_order_acq_rel, std::memory_order_acquire);
150 auto oldval =
count();
152 DCHECK_GT(oldval & kLinkMask, 0u);
153 if (oldval == kLink) {
157 if (count_cas(oldval, oldval -
sub)) {
165 auto oldval =
count();
173 DCHECK_GT(oldval & kRefMask, 0u);
174 if (count_cas(oldval, oldval -
sub)) {
181 auto oldval =
count();
182 auto sub = kLink - kRef;
184 if (oldval == kLink) {
188 if (count_cas(oldval, oldval -
sub)) {
189 return (oldval & kLinkMask) == kLink;
233 template <
typename T,
template <
typename>
class Atom,
typename D>
236 using Stack = std::stack<hazptr_obj_base_linked<T, Atom, D>*>;
240 this->pre_retire_check();
242 this->push_to_retired(
243 default_hazptr_domain<Atom>());
248 if (this->release_link()) {
249 downgrade_retire_immutable_descendants();
259 if (this->release_link()) {
260 DCHECK_EQ(this->
count(), 0u);
269 if (obj->release_ref()) {
271 obj->release_retire_mutable_children(l);
279 call_push_links(
false, s);
283 if (p && p->downgrade_link()) {
284 p->call_push_links(
false, s);
292 call_push_links(
false, s);
296 if (p && p->release_ref()) {
297 p->call_push_links(
false, s);
305 call_push_links(
true, s);
309 if (p->release_link()) {
310 p->pre_retire_check();
318 static_cast<T*
>(
this)->push_links(m, s);
322 this->delete_obj(static_cast<T*>(
this));
Count count() const noexcept
void acquire_link() noexcept
void push(hazptr_obj< Atom > *obj)
bool count_cas(Count &oldval, Count newval) noexcept
void count_inc_safe(Count add) noexcept
—— Concurrent Priority Queue Implementation ——
requires E e noexcept(noexcept(s.error(std::move(e))))
void set_reclaim() noexcept
void count_inc(Count add) noexcept
const Atom< T * > & operator()() const noexcept
void count_set(Count val) noexcept
bool downgrade_link() noexcept
Atom< T * > & operator()() noexcept
static map< string, int > m
void downgrade_retire_immutable_descendants()
bool release_ref() noexcept
void release_delete_immutable_descendants()
void acquire_ref_safe() noexcept
hazptr_root(T *p=nullptr) noexcept
std::stack< hazptr_obj_base_linked< NodeAuto< Atom >, Atom, D > * > Stack
void acquire_ref() noexcept
void release_retire_mutable_children(hazptr_obj_list< Atom > &l)
void acquire_link_safe() noexcept
void call_push_links(bool m, Stack &s)
bool release_link() noexcept
void unlink_and_reclaim_unchecked()