Commit 7046d43c authored by Dave Watson's avatar Dave Watson Committed by Facebook Github Bot

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
parent 79376dc7
...@@ -602,6 +602,11 @@ FOLLY_ALWAYS_INLINE hazptr_domain& default_hazptr_domain() { ...@@ -602,6 +602,11 @@ FOLLY_ALWAYS_INLINE hazptr_domain& default_hazptr_domain() {
return default_domain_; return default_domain_;
} }
template <typename T, typename D>
FOLLY_ALWAYS_INLINE void hazptr_retire(T* obj, D reclaim) {
default_hazptr_domain().retire(obj, std::move(reclaim));
}
/** hazptr_rec */ /** hazptr_rec */
FOLLY_ALWAYS_INLINE void hazptr_rec::set(const void* p) noexcept { FOLLY_ALWAYS_INLINE void hazptr_rec::set(const void* p) noexcept {
...@@ -649,6 +654,21 @@ inline const void* hazptr_obj::getObjPtr() const { ...@@ -649,6 +654,21 @@ inline const void* hazptr_obj::getObjPtr() const {
/** hazptr_domain */ /** hazptr_domain */
template <typename T, typename D>
void hazptr_domain::retire(T* obj, D reclaim) {
struct hazptr_retire_node : hazptr_obj {
std::unique_ptr<T, D> 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<hazptr_retire_node*>(p);
};
objRetire(node);
}
inline hazptr_domain::~hazptr_domain() { inline hazptr_domain::~hazptr_domain() {
DEBUG_PRINT(this); DEBUG_PRINT(this);
{ /* reclaim all remaining retired objects */ { /* reclaim all remaining retired objects */
......
...@@ -62,6 +62,10 @@ class hazptr_domain { ...@@ -62,6 +62,10 @@ class hazptr_domain {
hazptr_domain& operator=(const hazptr_domain&) = delete; hazptr_domain& operator=(const hazptr_domain&) = delete;
hazptr_domain& operator=(hazptr_domain&&) = delete; hazptr_domain& operator=(hazptr_domain&&) = delete;
/** Free-function retire. May allocate memory */
template <typename T, typename D = std::default_delete<T>>
void retire(T* obj, D reclaim = {});
private: private:
friend class hazptr_holder; friend class hazptr_holder;
template <typename, typename> template <typename, typename>
...@@ -90,6 +94,10 @@ hazptr_domain& default_hazptr_domain(); ...@@ -90,6 +94,10 @@ hazptr_domain& default_hazptr_domain();
extern hazptr_domain default_domain_; extern hazptr_domain default_domain_;
/** Free-function retire, that operates on the default domain */
template <typename T, typename D = std::default_delete<T>>
void hazptr_retire(T* obj, D reclaim = {});
/** Definition of hazptr_obj */ /** Definition of hazptr_obj */
class hazptr_obj { class hazptr_obj {
friend class hazptr_domain; friend class hazptr_domain;
......
...@@ -551,3 +551,25 @@ TEST_F(HazptrTest, mt_refcount) { ...@@ -551,3 +551,25 @@ TEST_F(HazptrTest, mt_refcount) {
CHECK_EQ(constructed.load(), num); CHECK_EQ(constructed.load(), num);
CHECK_EQ(destroyed.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);
}
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