X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=folly%2Fexperimental%2Fhazptr%2Fhazptr-impl.h;h=83f43b6f005e68d8e2097fd89fb5004e5fb9ae7b;hb=028415ba5c1fee579d249a97dd49752fe3c7348b;hp=5c343c5c7a6dc1058a0403f49131e611deb968c2;hpb=e7f26d60480810d6c2b724130e35761d75af33fc;p=folly.git diff --git a/folly/experimental/hazptr/hazptr-impl.h b/folly/experimental/hazptr/hazptr-impl.h index 5c343c5c..83f43b6f 100644 --- a/folly/experimental/hazptr/hazptr-impl.h +++ b/folly/experimental/hazptr/hazptr-impl.h @@ -216,14 +216,7 @@ inline void hazptr_obj_base_refcounted::retire( hazptr_domain& domain, D deleter) { DEBUG_PRINT(this << " " << &domain); - deleter_ = std::move(deleter); - reclaim_ = [](hazptr_obj* p) { - auto hrobp = static_cast(p); - if (hrobp->release_ref()) { - auto obj = static_cast(hrobp); - hrobp->deleter_(obj); - } - }; + preRetire(deleter); if (HAZPTR_PRIV && (HAZPTR_ONE_DOMAIN || (&domain == &default_hazptr_domain()))) { if (hazptr_priv_try_retire(this)) { @@ -264,6 +257,19 @@ inline bool hazptr_obj_base_refcounted::release_ref() { return oldval == 0; } +template +inline void hazptr_obj_base_refcounted::preRetire(D deleter) { + DCHECK(next_ == nullptr); + deleter_ = std::move(deleter); + reclaim_ = [](hazptr_obj* p) { + auto hrobp = static_cast(p); + if (hrobp->release_ref()) { + auto obj = static_cast(hrobp); + hrobp->deleter_(obj); + } + }; +} + /** * hazptr_rec */ @@ -680,6 +686,7 @@ inline hazptr_domain::~hazptr_domain() { while (retired) { for (auto p = retired; p; p = next) { next = p->next_; + DCHECK(p != next); DEBUG_PRINT(this << " " << p << " " << p->reclaim_); (*(p->reclaim_))(p); } @@ -787,6 +794,7 @@ inline void hazptr_domain::bulkReclaim() { hazptr_obj* next; for (; p; p = next) { next = p->next_; + DCHECK(p != next); if (hs.count(p->getObjPtr()) == 0) { DEBUG_PRINT(this << " " << p << " " << p->reclaim_); (*(p->reclaim_))(p); @@ -1071,5 +1079,73 @@ inline hazptr_tls_life::~hazptr_tls_life() { tls_state_ = TLS_DESTROYED; } +/** hazptr_obj_batch */ +/* Only for default domain. Supports only hazptr_obj_base_refcounted + * and a thread-safe access only, for now. */ + +class hazptr_obj_batch { + static constexpr size_t DefaultThreshold = 20; + hazptr_obj* head_{nullptr}; + hazptr_obj* tail_{nullptr}; + size_t rcount_{0}; + size_t threshold_{DefaultThreshold}; + + public: + hazptr_obj_batch() {} + hazptr_obj_batch(hazptr_obj* head, hazptr_obj* tail, size_t rcount) + : head_(head), tail_(tail), rcount_(rcount) {} + + ~hazptr_obj_batch() { + retire_all(); + } + + /* Prepare a hazptr_obj_base_refcounted for retirement but don't + push it the domain yet. Return true if the batch is ready. */ + template > + hazptr_obj_batch prep_retire_refcounted( + hazptr_obj_base_refcounted* obj, + D deleter = {}) { + obj->preRetire(deleter); + obj->next_ = head_; + head_ = obj; + if (tail_ == nullptr) { + tail_ = obj; + } + if (++rcount_ < threshold_) { + return hazptr_obj_batch(); + } else { + auto head = head_; + auto tail = tail_; + auto rcount = rcount_; + clear(); + return hazptr_obj_batch(head, tail, rcount); + } + } + + bool empty() { + return rcount_ == 0; + } + + void retire_all() { + if (!empty()) { + auto& domain = default_hazptr_domain(); + domain.pushRetired(head_, tail_, rcount_); + domain.tryBulkReclaim(); + clear(); + } + } + + void set_threshold(size_t thresh) { + threshold_ = thresh; + } + + private: + void clear() { + head_ = nullptr; + tail_ = nullptr; + rcount_ = 0; + } +}; + } // namespace hazptr } // namespace folly