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
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 */
FOLLY_ALWAYS_INLINE void hazptr_rec::set(const void* p) noexcept {
/** 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() {
DEBUG_PRINT(this);
{ /* reclaim all remaining retired objects */
hazptr_domain& operator=(const 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:
friend class hazptr_holder;
template <typename, typename>
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 */
class hazptr_obj {
friend class hazptr_domain;
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);
+}