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

Fix destruction order

Summary:
- Added `hazptr.cpp` and `memory_resource.cpp`. Moved singleton code to source.
  - Changed the singleton for the default `hazptr_domain` to a global.
  - Changed hazptr_stats singleton to a global.
  - Moved the thread caching calls from the hazptr_domain functions to the constructor/destructor of hazptr_holder.
  - Changed the TLS singletons to TLS globals.
  - Changed some inlining directives.
  - Leak the hazptr_rec-s in the default domain

Reviewed By: davidtgoldblatt, djwatson

Differential Revision: D5553753

fbshipit-source-id: da69eecec55c0f78fb8ef5591f9aeffee99ff3fa
parent cccde53e
......@@ -98,7 +98,6 @@ inline uint64_t bench(std::string name, int ops, const RepFunc& repFn) {
inline uint64_t listBench(std::string name, int nthreads, int size) {
int ops = 100000;
auto repFn = [&] {
hazptr_holder dummy[100];
SWMRListSet<uint64_t> s;
auto init = [&] {
for (int i = 0; i < size; ++i) {
......@@ -119,7 +118,6 @@ inline uint64_t listBench(std::string name, int nthreads, int size) {
inline uint64_t holderBench(std::string name, int nthreads) {
int ops = 100000;
auto repFn = [&] {
hazptr_holder dummy[100];
auto init = [] {};
auto fn = [&](int tid) {
for (int j = tid; j < ops; j += nthreads) {
......@@ -138,7 +136,6 @@ inline uint64_t retireBench(std::string name, int nthreads) {
};
int ops = 100000;
auto repFn = [&] {
hazptr_holder dummy[100];
auto init = [] {};
auto fn = [&](int tid) {
for (int j = tid; j < ops; j += nthreads) {
......
......@@ -53,7 +53,6 @@ class SWMRListSet {
};
std::atomic<Node*> head_ = {nullptr};
hazptr_domain& domain_;
/* Used by the single writer */
void locate_lower_bound(const T& v, std::atomic<Node*>*& prev) const {
......@@ -67,9 +66,6 @@ class SWMRListSet {
}
public:
explicit SWMRListSet(hazptr_domain& domain = default_hazptr_domain())
: domain_(domain) {}
~SWMRListSet() {
Node* next;
for (auto p = head_.load(); p; p = next) {
......@@ -97,14 +93,15 @@ class SWMRListSet {
prev->store(curr_next, std::memory_order_release);
// ...and only then null out the removed node.
curr->next_.store(nullptr, std::memory_order_release);
curr->retire(domain_);
curr->retire();
return true;
}
/* Used by readers */
bool contains(const T& val) const {
/* Acquire two hazard pointers for hand-over-hand traversal. */
hazptr_holder hptr_prev(domain_);
hazptr_holder hptr_curr(domain_);
hazptr_holder hptr_prev;
hazptr_holder hptr_curr;
while (true) {
auto prev = &head_;
auto curr = prev->load(std::memory_order_acquire);
......
This diff is collapsed.
/*
* Copyright 2017 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "hazptr.h"
namespace folly {
namespace hazptr {
FOLLY_STATIC_CTOR_PRIORITY_MAX hazptr_domain default_domain_;
hazptr_stats hazptr_stats_;
thread_local hazptr_tls_state tls_state_ = TLS_UNINITIALIZED;
thread_local hazptr_tc tls_tc_data_;
thread_local hazptr_priv tls_priv_data_;
thread_local hazptr_tls_life tls_life_; // last
} // namespace hazptr
} // namespace folly
......@@ -51,7 +51,7 @@ class hazptr_domain {
friend class hazptr_holder;
template <typename, typename>
friend class hazptr_obj_base;
friend class hazptr_priv;
friend struct hazptr_priv;
memory_resource* mr_;
std::atomic<hazptr_rec*> hazptrs_ = {nullptr};
......@@ -71,12 +71,14 @@ class hazptr_domain {
/** Get the default hazptr_domain */
hazptr_domain& default_hazptr_domain();
extern hazptr_domain default_domain_;
/** Definition of hazptr_obj */
class hazptr_obj {
friend class hazptr_domain;
template <typename, typename>
friend class hazptr_obj_base;
friend class hazptr_priv;
friend struct hazptr_priv;
void (*reclaim_)(hazptr_obj*);
hazptr_obj* next_;
......
/*
* Copyright 2017 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "memory_resource.h"
namespace folly {
namespace hazptr {
memory_resource** default_mr_ptr() {
/* library-local */ static memory_resource* default_mr =
new_delete_resource();
DEBUG_PRINT(&default_mr << " " << default_mr);
return &default_mr;
}
memory_resource* get_default_resource() {
DEBUG_PRINT("");
return *default_mr_ptr();
}
void set_default_resource(memory_resource* mr) {
DEBUG_PRINT("");
*default_mr_ptr() = mr;
}
memory_resource* new_delete_resource() {
class new_delete : public memory_resource {
public:
void* allocate(
const size_t bytes,
const size_t alignment = folly::max_align_v) override {
(void)alignment;
void* p = static_cast<void*>(new char[bytes]);
DEBUG_PRINT(this << " " << p << " " << bytes);
return p;
}
void deallocate(
void* p,
const size_t bytes,
const size_t alignment = folly::max_align_v) override {
(void)alignment;
(void)bytes;
DEBUG_PRINT(p << " " << bytes);
delete[] static_cast<char*>(p);
}
};
static new_delete mr;
return &mr;
}
} // namespace hazptr
} // namespace folly
......@@ -22,6 +22,7 @@
/// std::pmr::memory_resource (C++17) as needed for developing a
/// hazptr prototype.
////////////////////////////////////////////////////////////////////////////////
#include <folly/Portability.h>
#include <memory>
......@@ -44,51 +45,5 @@ memory_resource* get_default_resource();
void set_default_resource(memory_resource*);
memory_resource* new_delete_resource();
////////////////////////////////////////////////////////////////////////////////
/// Implementation
////////////////////////////////////////////////////////////////////////////////
inline memory_resource** default_mr_ptr() {
/* library-local */ static memory_resource* default_mr =
new_delete_resource();
DEBUG_PRINT(&default_mr << " " << default_mr);
return &default_mr;
}
inline memory_resource* get_default_resource() {
DEBUG_PRINT("");
return *default_mr_ptr();
}
inline void set_default_resource(memory_resource* mr) {
DEBUG_PRINT("");
*default_mr_ptr() = mr;
}
inline memory_resource* new_delete_resource() {
class new_delete : public memory_resource {
public:
void* allocate(
const size_t bytes,
const size_t alignment = folly::max_align_v) override {
(void)alignment;
void* p = static_cast<void*>(new char[bytes]);
DEBUG_PRINT(this << " " << p << " " << bytes);
return p;
}
void deallocate(
void* p,
const size_t bytes,
const size_t alignment = folly::max_align_v) override {
(void)alignment;
(void)bytes;
DEBUG_PRINT(p << " " << bytes);
delete[] static_cast<char*>(p);
}
};
static new_delete mr;
return &mr;
}
} // namespace folly
} // namespace hazptr
......@@ -198,12 +198,11 @@ TEST_F(HazptrTest, LIFO) {
TEST_F(HazptrTest, SWMRLIST) {
using T = uint64_t;
hazptr_domain custom_domain;
CHECK_GT(FLAGS_num_threads, 0);
for (int i = 0; i < FLAGS_num_reps; ++i) {
DEBUG_PRINT("========== start of rep scope");
SWMRListSet<T> s(custom_domain);
SWMRListSet<T> s;
std::vector<std::thread> threads(FLAGS_num_threads);
for (int tid = 0; tid < FLAGS_num_threads; ++tid) {
threads[tid] = std::thread([&s, tid]() {
......
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