From: Dave Watson Date: Mon, 20 Nov 2017 16:18:27 +0000 (-0800) Subject: Add free-function retire X-Git-Tag: v2017.11.27.00~16 X-Git-Url: http://plrg.eecs.uci.edu/git/?p=folly.git;a=commitdiff_plain;h=7046d43c7e3c18ebc28c62141b8e1eefabce5323;hp=79376dc7937cd38c10c0c632e3b39c6955ebd734 Add free-function retire Summary: Adds a hazptr_retire and domain::retire methods to hazptr. They both allocate memory instead of inheriting. This will make implementation of google's cell proposal trivial, vs. D4754972 which felt overwraught. http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0561r0.html Reviewed By: magedm Differential Revision: D6361162 fbshipit-source-id: 9f259f434139f960483b2ab7c5190d3807edcf52 --- diff --git a/folly/experimental/hazptr/hazptr-impl.h b/folly/experimental/hazptr/hazptr-impl.h index e287aecc..823f2ebf 100644 --- a/folly/experimental/hazptr/hazptr-impl.h +++ b/folly/experimental/hazptr/hazptr-impl.h @@ -602,6 +602,11 @@ FOLLY_ALWAYS_INLINE hazptr_domain& default_hazptr_domain() { return default_domain_; } +template +FOLLY_ALWAYS_INLINE void hazptr_retire(T* obj, D reclaim) { + default_hazptr_domain().retire(obj, std::move(reclaim)); +} + /** hazptr_rec */ FOLLY_ALWAYS_INLINE void hazptr_rec::set(const void* p) noexcept { @@ -649,6 +654,21 @@ inline const void* hazptr_obj::getObjPtr() const { /** hazptr_domain */ +template +void hazptr_domain::retire(T* obj, D reclaim) { + struct hazptr_retire_node : hazptr_obj { + std::unique_ptr obj_; + + hazptr_retire_node(T* obj, D reclaim) : obj_{obj, std::move(reclaim)} {} + }; + + auto node = new hazptr_retire_node(obj, std::move(reclaim)); + node->reclaim_ = [](hazptr_obj* p) { + delete static_cast(p); + }; + objRetire(node); +} + inline hazptr_domain::~hazptr_domain() { DEBUG_PRINT(this); { /* reclaim all remaining retired objects */ diff --git a/folly/experimental/hazptr/hazptr.h b/folly/experimental/hazptr/hazptr.h index 62d96514..48e8392a 100644 --- a/folly/experimental/hazptr/hazptr.h +++ b/folly/experimental/hazptr/hazptr.h @@ -62,6 +62,10 @@ class hazptr_domain { hazptr_domain& operator=(const hazptr_domain&) = delete; hazptr_domain& operator=(hazptr_domain&&) = delete; + /** Free-function retire. May allocate memory */ + template > + void retire(T* obj, D reclaim = {}); + private: friend class hazptr_holder; template @@ -90,6 +94,10 @@ hazptr_domain& default_hazptr_domain(); extern hazptr_domain default_domain_; +/** Free-function retire, that operates on the default domain */ +template > +void hazptr_retire(T* obj, D reclaim = {}); + /** Definition of hazptr_obj */ class hazptr_obj { friend class hazptr_domain; diff --git a/folly/experimental/hazptr/test/HazptrTest.cpp b/folly/experimental/hazptr/test/HazptrTest.cpp index 9d71cda3..89ddc023 100644 --- a/folly/experimental/hazptr/test/HazptrTest.cpp +++ b/folly/experimental/hazptr/test/HazptrTest.cpp @@ -551,3 +551,25 @@ TEST_F(HazptrTest, mt_refcount) { CHECK_EQ(constructed.load(), num); CHECK_EQ(destroyed.load(), num); } + +TEST_F(HazptrTest, FreeFunctionRetire) { + auto foo = new int; + hazptr_retire(foo); + auto foo2 = new int; + hazptr_retire(foo2, [](int* obj) { delete obj; }); + + bool retired = false; + { + hazptr_domain myDomain0; + struct delret { + bool* retired_; + delret(bool* retire) : retired_(retire) {} + ~delret() { + *retired_ = true; + } + }; + auto foo3 = new delret(&retired); + myDomain0.retire(foo3); + } + EXPECT_TRUE(retired); +}