20 #if FOLLY_HAZPTR_THR_LOCAL 27 #include <glog/logging.h> 42 template <
template <
typename>
class Atom>
43 class hazptr_tc_entry {
44 hazptr_rec<Atom>* hprec_;
46 template <u
int8_t,
template <
typename>
class>
47 friend class hazptr_array;
48 template <u
int8_t,
template <
typename>
class>
49 friend class hazptr_local;
50 friend class hazptr_tc<
Atom>;
70 template <
template <
typename>
class Atom>
72 static constexpr
uint8_t kCapacity = 9;
74 hazptr_tc_entry<Atom> entry_[kCapacity];
90 template <u
int8_t,
template <
typename>
class>
91 friend class hazptr_array;
92 friend class hazptr_holder<
Atom>;
93 template <u
int8_t,
template <
typename>
class>
94 friend class hazptr_local;
98 DCHECK(
i <= capacity());
104 auto hprec = entry_[--count_].get();
111 if (
LIKELY(count_ < capacity())) {
112 entry_[count_++].fill(hprec);
127 DCHECK_LE(count_ + num, capacity());
128 auto& domain = default_hazptr_domain<Atom>();
130 auto hprec = domain.hprec_acquire();
131 entry_[count_++].fill(hprec);
136 DCHECK_GE(count_, num);
138 entry_[--count_].evict();
152 template <
template <
typename>
class Atom>
162 template <
template <
typename>
class Atom>
164 static constexpr
int kThreshold = 20;
166 Atom<hazptr_obj<Atom>*> head_;
167 Atom<hazptr_obj<Atom>*> tail_;
172 hazptr_priv() : head_(
nullptr), tail_(
nullptr), rcount_(0), in_dtor_(false) {}
177 push_all_to_domain(
false);
182 friend class hazptr_domain<
Atom>;
183 friend class hazptr_obj<
Atom>;
186 return head() ==
nullptr;
189 void push(hazptr_obj<Atom>* obj) {
191 push_in_priv_list(obj);
194 void push_in_priv_list(hazptr_obj<Atom>* obj) {
197 if (push_in_non_empty_list(obj)) {
201 if (push_in_empty_list(obj)) {
206 if (++rcount_ >= kThreshold) {
207 push_all_to_domain(
true);
211 void push_all_to_domain(
bool check_to_reclaim) {
212 hazptr_obj<Atom>*
h =
nullptr;
213 hazptr_obj<Atom>*
t =
nullptr;
217 hazptr_obj_list<Atom> l(h, t, rcount_);
218 hazptr_domain_push_retired<Atom>(l, check_to_reclaim);
224 hazptr_obj<Atom>*& colHead,
225 hazptr_obj<Atom>*& colTail)
noexcept {
228 auto h = exchange_head();
230 auto t = exchange_tail();
233 colTail->set_next(h);
242 return head_.load(std::memory_order_acquire);
246 return tail_.load(std::memory_order_acquire);
249 void set_head(hazptr_obj<Atom>* obj)
noexcept {
250 head_.store(obj, std::memory_order_release);
253 bool cas_head(hazptr_obj<Atom>* expected, hazptr_obj<Atom>* obj)
noexcept {
254 return head_.compare_exchange_weak(
255 expected, obj, std::memory_order_acq_rel, std::memory_order_relaxed);
258 bool cas_tail(hazptr_obj<Atom>* expected, hazptr_obj<Atom>* obj)
noexcept {
259 return tail_.compare_exchange_weak(
260 expected, obj, std::memory_order_acq_rel, std::memory_order_relaxed);
263 hazptr_obj<Atom>* exchange_head()
noexcept {
264 return head_.exchange(
nullptr, std::memory_order_acq_rel);
267 hazptr_obj<Atom>* exchange_tail()
noexcept {
268 return tail_.exchange(
nullptr, std::memory_order_acq_rel);
271 bool push_in_non_empty_list(hazptr_obj<Atom>* obj)
noexcept {
275 if (cas_head(h, obj)) {
282 bool push_in_empty_list(hazptr_obj<Atom>* obj)
noexcept {
283 hazptr_obj<Atom>* t =
nullptr;
284 obj->set_next(
nullptr);
285 if (cas_tail(t, obj)) {
296 template <
template <
typename>
class Atom>
297 using hazptr_priv_singleton =
300 template <
template <
typename>
class Atom>
307 #endif // FOLLY_HAZPTR_THR_LOCAL
#define FOLLY_ALWAYS_INLINE
—— Concurrent Priority Queue Implementation ——
requires E e noexcept(noexcept(s.error(std::move(e))))
hazptr_priv< Atom > & hazptr_priv_tls()
constexpr auto empty(C const &c) -> decltype(c.empty())
hazptr_tc< Atom > & hazptr_tc_tls()
Future< std::vector< typename std::iterator_traits< InputIterator >::value_type::value_type > > collect(InputIterator first, InputIterator last)
PUSHMI_INLINE_VAR constexpr detail::get_fn< T > get