From: Dave Watson <davejwatson@fb.com>
Date: Wed, 26 Apr 2017 16:56:26 +0000 (-0700)
Subject: Fix virtual struct bug
X-Git-Tag: v2017.05.01.00~11
X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=92f554a525fc603232cc80b4603e4d43ec6b50de;p=folly.git

Fix virtual struct bug

Summary: virtual classes currently don't work in hazard pointers, and get incorrectly reclaimed.

Reviewed By: magedm

Differential Revision: D4951584

fbshipit-source-id: 8200df6bb8d500af2e89086edf7835d4fb90b6a2
---

diff --git a/folly/experimental/hazptr/hazptr-impl.h b/folly/experimental/hazptr/hazptr-impl.h
index 1ed15244..ecf6865d 100644
--- a/folly/experimental/hazptr/hazptr-impl.h
+++ b/folly/experimental/hazptr/hazptr-impl.h
@@ -108,8 +108,9 @@ inline T* hazptr_owner<T>::get_protected(const A& src) noexcept {
 
 template <typename T>
 inline void hazptr_owner<T>::set(const T* ptr) noexcept {
-  DEBUG_PRINT(this << " " << ptr);
-  hazptr_->set(ptr);
+  auto p = static_cast<hazptr_obj*>(const_cast<T*>(ptr));
+  DEBUG_PRINT(this << " " << ptr << " p:" << p);
+  hazptr_->set(p);
 }
 
 template <typename T>
diff --git a/folly/experimental/hazptr/hazptr.h b/folly/experimental/hazptr/hazptr.h
index 464dc1f3..d06cefcb 100644
--- a/folly/experimental/hazptr/hazptr.h
+++ b/folly/experimental/hazptr/hazptr.h
@@ -89,7 +89,7 @@ class hazptr_obj {
 
 /** Definition of hazptr_obj_base */
 template <typename T, typename Deleter = std::default_delete<T>>
-class hazptr_obj_base : private hazptr_obj {
+class hazptr_obj_base : public hazptr_obj {
  public:
   /* Retire a removed object and pass the responsibility for
    * reclaiming it to the hazptr library */
diff --git a/folly/experimental/hazptr/test/HazptrTest.cpp b/folly/experimental/hazptr/test/HazptrTest.cpp
index bcabbe72..fa4ac1ec 100644
--- a/folly/experimental/hazptr/test/HazptrTest.cpp
+++ b/folly/experimental/hazptr/test/HazptrTest.cpp
@@ -238,3 +238,21 @@ TEST_F(HazptrTest, WIDECAS) {
   ret = s.cas(u, v);
   CHECK(ret);
 }
+
+TEST_F(HazptrTest, VirtualTest) {
+  struct Thing : public hazptr_obj_base<Thing> {
+    virtual ~Thing() {
+      DEBUG_PRINT("this: " << this << " &a: " << &a << " a: " << a);
+    }
+    int a;
+  };
+  for (int i = 0; i < 100; i++) {
+    auto bar = new Thing;
+    bar->a = i;
+
+    hazptr_owner<Thing> hptr;
+    hptr.set(bar);
+    bar->retire();
+    EXPECT_EQ(bar->a, i);
+  }
+}