Commit ea244c69 authored by Maged Michael's avatar Maged Michael Committed by Facebook Github Bot

ConcurrentHashMap: Use synchronization/hazptr and hazptr_obj_base_linked

Summary:
- Use the hazard pointer library under folly/synchronization.
  - NodeT derived from hazptr_obj_base_linked.
  - Bucket heads are hazptr_root-s with dtor that automatically unlinks nodes
  - Provides support for uncertain removal of NodeT-s both from NodeT and Buckets
  - As intended, hazptr_cleanup reclaims all unprotected removed objects even if they have not been determined to be retirable at the start of cleanup.

Fixes the following:
- The pattern of calling h.get_protected(node->next_), when hazptr_holder h is protecting node is unsafe because try_protect (inside get_protected) may fail and we end protecting neither node nor next. This diff uses a different hazptr_holder to protect the next node. A correct pattern is to call h2.get_protected(node->next_) then h.swap(h2); h2.reset();
- The pattern of calling h2.reset(node) then h1.reset() to continue protecting a node already protected by h1 is unsafe because h2's protection may be too late after node was retired. A correct pattern is h2.swap(h1).

Reviewed By: djwatson

Differential Revision: D7708325

fbshipit-source-id: 617dcfe19410071888abafa32f0e1ada9d123983
parent 8fb5c152
......@@ -17,7 +17,7 @@
#include <folly/Optional.h>
#include <folly/concurrency/detail/ConcurrentHashMap-detail.h>
#include <folly/experimental/hazptr/hazptr.h>
#include <folly/synchronization/Hazptr.h>
#include <atomic>
#include <mutex>
......
......@@ -25,7 +25,6 @@
#include <folly/test/DeterministicSchedule.h>
using namespace folly::test;
using namespace folly::hazptr;
using namespace folly;
using namespace std;
......@@ -610,6 +609,8 @@ TEST(ConcurrentHashMap, Deletion) {
map.insert(0, std::make_shared<Wrapper>(del));
}
folly::hazptr_cleanup();
EXPECT_TRUE(del);
}
......@@ -623,7 +624,7 @@ TEST(ConcurrentHashMap, DeletionWithErase) {
map.erase(0);
}
hazptr_cleanup();
folly::hazptr_cleanup();
EXPECT_TRUE(del);
}
......@@ -639,7 +640,7 @@ TEST(ConcurrentHashMap, DeletionWithIterator) {
map.erase(it);
}
hazptr_cleanup();
folly::hazptr_cleanup();
EXPECT_TRUE(del);
}
......@@ -656,6 +657,8 @@ TEST(ConcurrentHashMap, DeletionWithForLoop) {
}
}
folly::hazptr_cleanup();
EXPECT_TRUE(del);
}
......@@ -669,6 +672,8 @@ TEST(ConcurrentHashMap, DeletionMultiple) {
map.insert(1, std::make_shared<Wrapper>(del2));
}
folly::hazptr_cleanup();
EXPECT_TRUE(del1);
EXPECT_TRUE(del2);
}
......@@ -683,7 +688,7 @@ TEST(ConcurrentHashMap, DeletionAssigned) {
map.insert_or_assign(0, std::make_shared<Wrapper>(del2));
}
hazptr_cleanup();
folly::hazptr_cleanup();
EXPECT_TRUE(del1);
EXPECT_TRUE(del2);
......@@ -700,7 +705,7 @@ TEST(ConcurrentHashMap, DeletionMultipleMaps) {
map2.insert(0, std::make_shared<Wrapper>(del2));
}
hazptr_cleanup();
folly::hazptr_cleanup();
EXPECT_TRUE(del1);
EXPECT_TRUE(del2);
......
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