From: Dave Watson Date: Wed, 3 May 2017 17:57:29 +0000 (-0700) Subject: Domain destruction fixes X-Git-Tag: v2017.05.08.00~18 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=90c8861ca8d315a3e6bbca84d095b8f8dd2496a7;p=folly.git Domain destruction fixes Summary: If a retired object's destructor retire()s other hazard pointers, currently these are not cleaned up correctly when the domain destructs. Retired pointers must be cleaned up before destroying hazptr_recs, and must be done iteratively until no more garbage is generated. Reviewed By: magedm Differential Revision: D4987333 fbshipit-source-id: bcdd61abb47caca0892a8c4dbb864d17d4f2fa30 --- diff --git a/folly/experimental/hazptr/hazptr-impl.h b/folly/experimental/hazptr/hazptr-impl.h index ecf6865d..50874df7 100644 --- a/folly/experimental/hazptr/hazptr-impl.h +++ b/folly/experimental/hazptr/hazptr-impl.h @@ -183,6 +183,17 @@ inline const void* hazptr_obj::getObjPtr() const { inline hazptr_domain::~hazptr_domain() { DEBUG_PRINT(this); + { /* reclaim all remaining retired objects */ + hazptr_obj* next; + auto retired = retired_.exchange(nullptr); + while (retired) { + for (auto p = retired; p; p = next) { + next = p->next_; + (*(p->reclaim_))(p); + } + retired = retired_.exchange(nullptr); + } + } { /* free all hazptr_rec-s */ hazptr_rec* next; for (auto p = hazptrs_.load(); p; p = next) { @@ -190,13 +201,6 @@ inline hazptr_domain::~hazptr_domain() { mr_->deallocate(static_cast(p), sizeof(hazptr_rec)); } } - { /* reclaim all remaining retired objects */ - hazptr_obj* next; - for (auto p = retired_.load(); p; p = next) { - next = p->next_; - (*(p->reclaim_))(p); - } - } } inline void hazptr_domain::try_reclaim() { diff --git a/folly/experimental/hazptr/test/HazptrTest.cpp b/folly/experimental/hazptr/test/HazptrTest.cpp index fa4ac1ec..20505262 100644 --- a/folly/experimental/hazptr/test/HazptrTest.cpp +++ b/folly/experimental/hazptr/test/HazptrTest.cpp @@ -256,3 +256,22 @@ TEST_F(HazptrTest, VirtualTest) { EXPECT_EQ(bar->a, i); } } + +TEST_F(HazptrTest, DestructionTest) { + hazptr_domain myDomain0; + struct Thing : public hazptr_obj_base { + Thing* next; + Thing(Thing* n) : next(n) {} + ~Thing() { + DEBUG_PRINT("this: " << this << " next: " << next); + if (next) { + next->retire(); + } + } + }; + Thing* last{nullptr}; + for (int i = 0; i < 2000; i++) { + last = new Thing(last); + } + last->retire(); +}