Commit 9feea971 authored by Maged Michael's avatar Maged Michael Committed by Facebook Github Bot

hazptr: Allow destruction of obj batch after default domain

Summary:
Allow hazptr_obj_batch-es to outlive the default domain.

Background: Until now it was expected that batches are destructed before the destruction of the default domain. This may be restrictive to good use cases.

This diff removes the above mentioned restriction and gives hazptr_obj_batch::shutdown_and_reclaim() to decide whether or not to access the default domain by supporting a singleton bool in default_hazptr_domain_alive() that could be made to outlive the default domain by calling that function before constructing the user object that may outlive the default domain.

Reviewed By: aary

Differential Revision: D18297698

fbshipit-source-id: 6021479ab36ce86d2c411fd71974fde47f7502a2
parent ddf4beb9
......@@ -132,6 +132,10 @@ class hazptr_domain;
template <template <typename> class Atom = std::atomic>
hazptr_domain<Atom>& default_hazptr_domain();
/** default_hazptr_domain_alive */
template <template <typename> class Atom = std::atomic>
bool& default_hazptr_domain_alive();
/** hazptr_domain_push_list */
template <template <typename> class Atom = std::atomic>
void hazptr_domain_push_list(
......
......@@ -133,14 +133,26 @@ class hazptr_domain {
public:
/** Constructor */
hazptr_domain() = default;
hazptr_domain() {
if (std::is_same<Atom<int>, std::atomic<int>>{} &&
this == &default_hazptr_domain<Atom>()) {
set_default_hazptr_domain_alive(true);
}
}
/** Destructor */
~hazptr_domain() {
shutdown_ = true;
reclaim_all_objects();
free_hazptr_recs();
DCHECK(tagged_.empty());
if (!tagged_.empty()) {
auto head = tagged_.pop_all(RetiredList::kDontLock);
reclaim_list_transitive(head);
}
if (std::is_same<Atom<int>, std::atomic<int>>{} &&
this == &default_hazptr_domain<Atom>()) {
set_default_hazptr_domain_alive(false);
}
}
hazptr_domain(const hazptr_domain&) = delete;
......@@ -583,6 +595,10 @@ class hazptr_domain {
hcount_.fetch_add(1);
return rec;
}
void set_default_hazptr_domain_alive(bool b) {
default_hazptr_domain_alive<Atom>() = b;
}
}; // hazptr_domain
/**
......@@ -611,6 +627,12 @@ FOLLY_ALWAYS_INLINE hazptr_domain<Atom>& default_hazptr_domain() {
return hazptr_default_domain_helper<Atom>::get();
}
template <template <typename> class Atom>
bool& default_hazptr_domain_alive() {
static bool alive = false;
return alive;
}
/** hazptr_domain_push_retired: push a list of retired objects into a domain */
template <template <typename> class Atom>
void hazptr_domain_push_retired(
......
......@@ -331,7 +331,8 @@ class hazptr_obj_batch {
Obj* obj = l.head();
reclaim_list(obj);
}
if (pushed_to_domain_tagged_.load(std::memory_order_relaxed)) {
if (pushed_to_domain_tagged_.load(std::memory_order_relaxed) &&
default_hazptr_domain_alive<Atom>()) {
default_hazptr_domain<Atom>().cleanup_batch_tag(this);
}
DCHECK(l_.empty());
......@@ -359,7 +360,7 @@ class hazptr_obj_batch {
/** push_obj */
void push_obj(Obj* obj) {
if (active_) {
if (active_ && default_hazptr_domain_alive<Atom>()) {
l_.push(obj);
inc_count();
check_threshold_push();
......@@ -384,6 +385,9 @@ class hazptr_obj_batch {
/** check_threshold_push */
void check_threshold_push() {
if (!default_hazptr_domain_alive<Atom>()) {
return;
}
auto c = count();
while (c >= kThreshold) {
if (cas_count(c, 0)) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment