proxygen
folly::hazptr_domain< Atom > Class Template Reference

#include <Hazptr-fwd.h>

Public Member Functions

 hazptr_domain ()=default
 
 ~hazptr_domain ()
 
 hazptr_domain (const hazptr_domain &)=delete
 
 hazptr_domain (hazptr_domain &&)=delete
 
hazptr_domainoperator= (const hazptr_domain &)=delete
 
hazptr_domainoperator= (hazptr_domain &&)=delete
 
template<typename T , typename D = std::default_delete<T>>
void retire (T *obj, D reclaim={})
 
void cleanup () noexcept
 

Private Member Functions

hazptr_rec< Atom > * hprec_acquire ()
 
void hprec_release (hazptr_rec< Atom > *hprec) noexcept
 
void push_retired (hazptr_obj_list< Atom > &l, bool check=true)
 
hazptr_rec< Atom > * head () const noexcept
 
hazptr_obj< Atom > * retired () const noexcept
 
int hcount () const noexcept
 
int rcount () const noexcept
 
bool reached_threshold (int rc, int hc) const noexcept
 
void reclaim_all_objects ()
 
void free_hazptr_recs ()
 
void check_cleanup_and_reclaim ()
 
void relaxed_cleanup () noexcept
 
void wait_for_zero_bulk_reclaims ()
 
void try_bulk_reclaim ()
 
void bulk_reclaim (bool transitive=false)
 
bool bulk_lookup_and_reclaim (hazptr_obj< Atom > *obj, const std::unordered_set< const void * > &hashset)
 
bool try_timed_cleanup ()
 
hazptr_rec< Atom > * try_acquire_existing_hprec ()
 
hazptr_rec< Atom > * acquire_new_hprec ()
 

Private Attributes

Atom< hazptr_rec< Atom > * > hazptrs_ {nullptr}
 
Atom< hazptr_obj< Atom > * > retired_ {nullptr}
 
Atom< uint64_tsync_time_ {0}
 
Atom< int > hcount_ {0}
 
Atom< int > rcount_ {0}
 
Atom< uint16_tnum_bulk_reclaims_ {0}
 
bool shutdown_ {false}
 

Static Private Attributes

static constexpr int kThreshold = detail::hazptr_domain_rcount_threshold()
 
static constexpr int kMultiplier = 2
 
static constexpr uint64_t kSyncTimePeriod {2000000000}
 

Friends

class hazptr_holder< Atom >
 
class hazptr_obj< Atom >
 
void hazptr_domain_push_retired (hazptr_obj_list< Atom > &, bool check, hazptr_domain< Atom > &) noexcept
 

Detailed Description

template<template< typename > class Atom>
class folly::hazptr_domain< Atom >

Hazard pointer domain Defined in HazptrDomain.hhazptr_domain

hazptr_domain

A domain manages a set of hazard pointers and a set of retired objects.

Most user code need not specify any domains.

Definition at line 120 of file Hazptr-fwd.h.

Constructor & Destructor Documentation

template<template< typename > class Atom>
folly::hazptr_domain< Atom >::hazptr_domain ( )
default

Constructor

template<template< typename > class Atom>
folly::hazptr_domain< Atom >::~hazptr_domain ( )
inline

Destructor

Definition at line 73 of file HazptrDomain.h.

73  {
74  shutdown_ = true;
77  }
template<template< typename > class Atom>
folly::hazptr_domain< Atom >::hazptr_domain ( const hazptr_domain< Atom > &  )
delete
template<template< typename > class Atom>
folly::hazptr_domain< Atom >::hazptr_domain ( hazptr_domain< Atom > &&  )
delete

Member Function Documentation

template<template< typename > class Atom>
hazptr_rec<Atom>* folly::hazptr_domain< Atom >::acquire_new_hprec ( )
inlineprivate

Definition at line 324 of file HazptrDomain.h.

324  {
325  auto rec = new hazptr_rec<Atom>;
326  rec->set_active();
327  rec->set_domain(this);
328  while (true) {
329  auto h = head();
330  rec->set_next(h);
331  if (hazptrs_.compare_exchange_weak(
332  h, rec, std::memory_order_release, std::memory_order_acquire)) {
333  break;
334  }
335  }
336  hcount_.fetch_add(1);
337  return rec;
338  }
*than *hazptr_holder h
Definition: Hazptr.h:116
Atom< hazptr_rec< Atom > * > hazptrs_
Definition: HazptrDomain.h:57
Atom< int > hcount_
Definition: HazptrDomain.h:63
hazptr_rec< Atom > * head() const noexcept
Definition: HazptrDomain.h:150
template<template< typename > class Atom>
bool folly::hazptr_domain< Atom >::bulk_lookup_and_reclaim ( hazptr_obj< Atom > *  obj,
const std::unordered_set< const void * > &  hashset 
)
inlineprivate

Definition at line 270 of file HazptrDomain.h.

272  {
273  hazptr_obj_list<Atom> children;
274  hazptr_obj_list<Atom> matched;
275  while (obj) {
276  auto next = obj->next();
277  DCHECK_NE(obj, next);
278  if (hashset.count(obj->raw_ptr()) == 0) {
279  (*(obj->reclaim()))(obj, children);
280  } else {
281  matched.push(obj);
282  }
283  obj = next;
284  }
285 #if FOLLY_HAZPTR_THR_LOCAL
286  if (!shutdown_) {
287  hazptr_priv_tls<Atom>().push_all_to_domain(false);
288  }
289 #endif
290  bool done = ((children.count() == 0) && (retired() == nullptr));
291  matched.splice(children);
292  if (matched.count() > 0) {
293  push_retired(matched, false /* don't call bulk_reclaim recursively */);
294  }
295  return done;
296  }
hazptr_obj< Atom > * retired() const noexcept
Definition: HazptrDomain.h:154
void push_retired(hazptr_obj_list< Atom > &l, bool check=true)
Definition: HazptrDomain.h:131
def next(obj)
Definition: ast.py:58
template<template< typename > class Atom>
void folly::hazptr_domain< Atom >::bulk_reclaim ( bool  transitive = false)
inlineprivate

Definition at line 251 of file HazptrDomain.h.

251  {
252  num_bulk_reclaims_.fetch_add(1, std::memory_order_acquire);
253  while (true) {
254  auto obj = retired_.exchange(nullptr, std::memory_order_acquire);
255  /*** Full fence ***/ asymmetricHeavyBarrier(AMBFlags::EXPEDITED);
256  auto rec = hazptrs_.load(std::memory_order_acquire);
257  /* Part 1 - read hazard pointer values into private search structure */
258  std::unordered_set<const void*> hashset; // TOTO: lock-free fixed hash set
259  for (; rec; rec = rec->next()) {
260  hashset.insert(rec->hazptr());
261  }
262  /* Part 2 - for each retired object, reclaim if no match */
263  if (bulk_lookup_and_reclaim(obj, hashset) || !transitive) {
264  break;
265  }
266  }
267  num_bulk_reclaims_.fetch_sub(1, std::memory_order_release);
268  }
bool bulk_lookup_and_reclaim(hazptr_obj< Atom > *obj, const std::unordered_set< const void * > &hashset)
Definition: HazptrDomain.h:270
Atom< hazptr_obj< Atom > * > retired_
Definition: HazptrDomain.h:58
Atom< hazptr_rec< Atom > * > hazptrs_
Definition: HazptrDomain.h:57
void asymmetricHeavyBarrier(AMBFlags flags)
Atom< uint16_t > num_bulk_reclaims_
Definition: HazptrDomain.h:65
template<template< typename > class Atom>
void folly::hazptr_domain< Atom >::check_cleanup_and_reclaim ( )
inlineprivate

Definition at line 203 of file HazptrDomain.h.

203  {
204  if (try_timed_cleanup()) {
205  return;
206  }
207  if (reached_threshold(rcount(), hcount())) {
209  }
210  }
int hcount() const noexcept
Definition: HazptrDomain.h:158
int rcount() const noexcept
Definition: HazptrDomain.h:162
bool reached_threshold(int rc, int hc) const noexcept
Definition: HazptrDomain.h:166
template<template< typename > class Atom>
void folly::hazptr_domain< Atom >::cleanup ( )
inlinenoexcept

cleanup

Definition at line 103 of file HazptrDomain.h.

103  {
104  relaxed_cleanup();
105  wait_for_zero_bulk_reclaims(); // wait for concurrent bulk_reclaim-s
106  }
void wait_for_zero_bulk_reclaims()
Definition: HazptrDomain.h:230
void relaxed_cleanup() noexcept
Definition: HazptrDomain.h:212
template<template< typename > class Atom>
void folly::hazptr_domain< Atom >::free_hazptr_recs ( )
inlineprivate

Definition at line 188 of file HazptrDomain.h.

188  {
189  /* Leak the hazard pointers for the default domain to avoid
190  destruction order issues with thread caches. */
191  if (this == &default_hazptr_domain<Atom>()) {
192  return;
193  }
194  auto rec = head();
195  while (rec) {
196  auto next = rec->next();
197  DCHECK(!rec->active());
198  delete rec;
199  rec = next;
200  }
201  }
hazptr_rec< Atom > * head() const noexcept
Definition: HazptrDomain.h:150
def next(obj)
Definition: ast.py:58
template<template< typename > class Atom>
int folly::hazptr_domain< Atom >::hcount ( ) const
inlineprivatenoexcept

Definition at line 158 of file HazptrDomain.h.

158  {
159  return hcount_.load(std::memory_order_acquire);
160  }
Atom< int > hcount_
Definition: HazptrDomain.h:63
template<template< typename > class Atom>
hazptr_rec<Atom>* folly::hazptr_domain< Atom >::head ( ) const
inlineprivatenoexcept

Definition at line 150 of file HazptrDomain.h.

150  {
151  return hazptrs_.load(std::memory_order_acquire);
152  }
Atom< hazptr_rec< Atom > * > hazptrs_
Definition: HazptrDomain.h:57
template<template< typename > class Atom>
hazptr_rec<Atom>* folly::hazptr_domain< Atom >::hprec_acquire ( )
inlineprivate

hprec_acquire

Definition at line 120 of file HazptrDomain.h.

120  {
121  auto rec = try_acquire_existing_hprec();
122  return rec != nullptr ? rec : acquire_new_hprec();
123  }
hazptr_rec< Atom > * try_acquire_existing_hprec()
Definition: HazptrDomain.h:312
hazptr_rec< Atom > * acquire_new_hprec()
Definition: HazptrDomain.h:324
template<template< typename > class Atom>
void folly::hazptr_domain< Atom >::hprec_release ( hazptr_rec< Atom > *  hprec)
inlineprivatenoexcept

hprec_release

Definition at line 126 of file HazptrDomain.h.

126  {
127  hprec->release();
128  }
template<template< typename > class Atom>
hazptr_domain& folly::hazptr_domain< Atom >::operator= ( const hazptr_domain< Atom > &  )
delete
template<template< typename > class Atom>
hazptr_domain& folly::hazptr_domain< Atom >::operator= ( hazptr_domain< Atom > &&  )
delete
template<template< typename > class Atom>
void folly::hazptr_domain< Atom >::push_retired ( hazptr_obj_list< Atom > &  l,
bool  check = true 
)
inlineprivate

push_retired

Definition at line 131 of file HazptrDomain.h.

131  {
132  /*** Full fence ***/ asymmetricLightBarrier();
133  while (true) {
134  auto r = retired();
135  l.tail()->set_next(r);
136  if (retired_.compare_exchange_weak(
137  r,
138  l.head(),
139  std::memory_order_release,
140  std::memory_order_acquire)) {
141  break;
142  }
143  }
144  rcount_.fetch_add(l.count(), std::memory_order_release);
145  if (check) {
147  }
148  }
hazptr_obj< Atom > * retired() const noexcept
Definition: HazptrDomain.h:154
Atom< int > rcount_
Definition: HazptrDomain.h:64
Atom< hazptr_obj< Atom > * > retired_
Definition: HazptrDomain.h:58
FOLLY_ALWAYS_INLINE void asymmetricLightBarrier()
void check_cleanup_and_reclaim()
Definition: HazptrDomain.h:203
bool check(const dynamic &schema, const dynamic &value, bool check=true)
template<template< typename > class Atom>
int folly::hazptr_domain< Atom >::rcount ( ) const
inlineprivatenoexcept

Definition at line 162 of file HazptrDomain.h.

162  {
163  return rcount_.load(std::memory_order_acquire);
164  }
Atom< int > rcount_
Definition: HazptrDomain.h:64
template<template< typename > class Atom>
bool folly::hazptr_domain< Atom >::reached_threshold ( int  rc,
int  hc 
) const
inlineprivatenoexcept

Definition at line 166 of file HazptrDomain.h.

166  {
167  return rc >= kThreshold && rc >= kMultiplier * hc;
168  }
static constexpr int kMultiplier
Definition: HazptrDomain.h:54
static constexpr int kThreshold
Definition: HazptrDomain.h:53
template<template< typename > class Atom>
void folly::hazptr_domain< Atom >::reclaim_all_objects ( )
inlineprivate

Definition at line 170 of file HazptrDomain.h.

170  {
171  auto retired = retired_.exchange(nullptr);
172  while (retired) {
173  auto obj = retired;
174  hazptr_obj_list<Atom> l;
175  while (obj) {
176  auto next = obj->next();
177  DCHECK(obj != next);
178  (*(obj->reclaim()))(obj, l);
179  obj = next;
180  }
181  if (l.count()) {
182  push_retired(l);
183  }
184  retired = retired_.exchange(nullptr);
185  }
186  }
hazptr_obj< Atom > * retired() const noexcept
Definition: HazptrDomain.h:154
Atom< hazptr_obj< Atom > * > retired_
Definition: HazptrDomain.h:58
void push_retired(hazptr_obj_list< Atom > &l, bool check=true)
Definition: HazptrDomain.h:131
def next(obj)
Definition: ast.py:58
template<template< typename > class Atom>
void folly::hazptr_domain< Atom >::relaxed_cleanup ( )
inlineprivatenoexcept

Definition at line 212 of file HazptrDomain.h.

212  {
213 #if FOLLY_HAZPTR_THR_LOCAL
214  hazptr_obj<Atom>* h = nullptr;
215  hazptr_obj<Atom>* t = nullptr;
216  for (hazptr_priv<Atom>& priv :
217  hazptr_priv_singleton<Atom>::accessAllThreads()) {
218  priv.collect(h, t);
219  }
220  if (h) {
221  DCHECK(t);
222  hazptr_obj_list<Atom> l(h, t, 0);
223  push_retired(l);
224  }
225 #endif
226  rcount_.store(0, std::memory_order_release);
227  bulk_reclaim(true);
228  }
*than *hazptr_holder h
Definition: Hazptr.h:116
Atom< int > rcount_
Definition: HazptrDomain.h:64
void bulk_reclaim(bool transitive=false)
Definition: HazptrDomain.h:251
void push_retired(hazptr_obj_list< Atom > &l, bool check=true)
Definition: HazptrDomain.h:131
friend class hazptr_obj< Atom >
Definition: HazptrDomain.h:114
template<template< typename > class Atom>
template<typename T , typename D = std::default_delete<T>>
void folly::hazptr_domain< Atom >::retire ( T obj,
D  reclaim = {} 
)
inline

retire - nonintrusive - allocates memory

Definition at line 87 of file HazptrDomain.h.

Referenced by free_function_retire_test().

87  {}) {
88  struct hazptr_retire_node : hazptr_obj<Atom> {
89  std::unique_ptr<T, D> obj_;
90  hazptr_retire_node(T* retireObj, D toReclaim)
91  : obj_{retireObj, std::move(toReclaim)} {}
92  };
93 
94  auto node = new hazptr_retire_node(obj, std::move(reclaim));
95  node->reclaim_ = [](hazptr_obj<Atom>* p, hazptr_obj_list<Atom>&) {
96  delete static_cast<hazptr_retire_node*>(p);
97  };
98  hazptr_obj_list<Atom> l(node);
99  push_retired(l);
100  }
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
folly::std T
#define D(name, bit)
Definition: CpuId.h:145
void push_retired(hazptr_obj_list< Atom > &l, bool check=true)
Definition: HazptrDomain.h:131
friend class hazptr_obj< Atom >
Definition: HazptrDomain.h:114
template<template< typename > class Atom>
hazptr_obj<Atom>* folly::hazptr_domain< Atom >::retired ( ) const
inlineprivatenoexcept

Definition at line 154 of file HazptrDomain.h.

154  {
155  return retired_.load(std::memory_order_acquire);
156  }
Atom< hazptr_obj< Atom > * > retired_
Definition: HazptrDomain.h:58
template<template< typename > class Atom>
hazptr_rec<Atom>* folly::hazptr_domain< Atom >::try_acquire_existing_hprec ( )
inlineprivate

Definition at line 312 of file HazptrDomain.h.

312  {
313  auto rec = head();
314  while (rec) {
315  auto next = rec->next();
316  if (rec->try_acquire()) {
317  return rec;
318  }
319  rec = next;
320  }
321  return nullptr;
322  }
hazptr_rec< Atom > * head() const noexcept
Definition: HazptrDomain.h:150
def next(obj)
Definition: ast.py:58
template<template< typename > class Atom>
void folly::hazptr_domain< Atom >::try_bulk_reclaim ( )
inlineprivate

Definition at line 236 of file HazptrDomain.h.

236  {
237  auto hc = hcount();
238  auto rc = rcount();
239  if (!reached_threshold(rc, hc)) {
240  return;
241  }
242  rc = rcount_.exchange(0, std::memory_order_release);
243  if (!reached_threshold(rc, hc)) {
244  /* No need to add rc back to rcount_. At least one concurrent
245  try_bulk_reclaim will proceed to bulk_reclaim. */
246  return;
247  }
248  bulk_reclaim();
249  }
int hcount() const noexcept
Definition: HazptrDomain.h:158
Atom< int > rcount_
Definition: HazptrDomain.h:64
void bulk_reclaim(bool transitive=false)
Definition: HazptrDomain.h:251
int rcount() const noexcept
Definition: HazptrDomain.h:162
bool reached_threshold(int rc, int hc) const noexcept
Definition: HazptrDomain.h:166
template<template< typename > class Atom>
bool folly::hazptr_domain< Atom >::try_timed_cleanup ( )
inlineprivate

Definition at line 298 of file HazptrDomain.h.

298  {
299  uint64_t time = std::chrono::duration_cast<std::chrono::nanoseconds>(
300  std::chrono::steady_clock::now().time_since_epoch())
301  .count();
302  auto prevtime = sync_time_.load(std::memory_order_relaxed);
303  if (time < prevtime ||
304  !sync_time_.compare_exchange_strong(
305  prevtime, time + kSyncTimePeriod, std::memory_order_relaxed)) {
306  return false;
307  }
308  relaxed_cleanup(); // calling regular cleanup may self deadlock
309  return true;
310  }
Atom< uint64_t > sync_time_
Definition: HazptrDomain.h:59
std::chrono::steady_clock::time_point now()
static constexpr uint64_t kSyncTimePeriod
Definition: HazptrDomain.h:55
void relaxed_cleanup() noexcept
Definition: HazptrDomain.h:212
int * count
std::chrono::nanoseconds time()
template<template< typename > class Atom>
void folly::hazptr_domain< Atom >::wait_for_zero_bulk_reclaims ( )
inlineprivate

Definition at line 230 of file HazptrDomain.h.

230  {
231  while (num_bulk_reclaims_.load(std::memory_order_acquire) > 0) {
233  }
234  }
Atom< uint16_t > num_bulk_reclaims_
Definition: HazptrDomain.h:65

Friends And Related Function Documentation

template<template< typename > class Atom>
void hazptr_domain_push_retired ( hazptr_obj_list< Atom > &  l,
bool  check = true,
hazptr_domain< Atom > &  domain = default_hazptr_domain<Atom>() 
)
friend

hazptr_domain_push_retired

hazptr_domain_push_retired: push a list of retired objects into a domain

Definition at line 369 of file HazptrDomain.h.

372  {
373  domain.push_retired(l, check);
374 }
bool check(const dynamic &schema, const dynamic &value, bool check=true)
template<template< typename > class Atom>
friend class hazptr_holder< Atom >
friend

Definition at line 113 of file HazptrDomain.h.

template<template< typename > class Atom>
friend class hazptr_obj< Atom >
friend

Definition at line 114 of file HazptrDomain.h.

Member Data Documentation

template<template< typename > class Atom>
Atom<hazptr_rec<Atom>*> folly::hazptr_domain< Atom >::hazptrs_ {nullptr}
private

Definition at line 57 of file HazptrDomain.h.

template<template< typename > class Atom>
Atom<int> folly::hazptr_domain< Atom >::hcount_ {0}
private

Definition at line 63 of file HazptrDomain.h.

template<template< typename > class Atom>
constexpr int folly::hazptr_domain< Atom >::kMultiplier = 2
staticprivate

Definition at line 54 of file HazptrDomain.h.

template<template< typename > class Atom>
constexpr uint64_t folly::hazptr_domain< Atom >::kSyncTimePeriod {2000000000}
staticprivate

Definition at line 55 of file HazptrDomain.h.

template<template< typename > class Atom>
constexpr int folly::hazptr_domain< Atom >::kThreshold = detail::hazptr_domain_rcount_threshold()
staticprivate

Definition at line 53 of file HazptrDomain.h.

template<template< typename > class Atom>
Atom<uint16_t> folly::hazptr_domain< Atom >::num_bulk_reclaims_ {0}
private

Definition at line 65 of file HazptrDomain.h.

template<template< typename > class Atom>
Atom<int> folly::hazptr_domain< Atom >::rcount_ {0}
private

Definition at line 64 of file HazptrDomain.h.

template<template< typename > class Atom>
Atom<hazptr_obj<Atom>*> folly::hazptr_domain< Atom >::retired_ {nullptr}
private

Definition at line 58 of file HazptrDomain.h.

template<template< typename > class Atom>
bool folly::hazptr_domain< Atom >::shutdown_ {false}
private

Definition at line 66 of file HazptrDomain.h.

Referenced by folly::hazptr_obj< Atom >::push_to_retired().

template<template< typename > class Atom>
Atom<uint64_t> folly::hazptr_domain< Atom >::sync_time_ {0}
private

Definition at line 59 of file HazptrDomain.h.


The documentation for this class was generated from the following files: