Commit 5e0a8b79 authored by Orvid King's avatar Orvid King Committed by Facebook Github Bot

Remove uses of liburcu

Summary: This only exists for perf comparisons, and has been unused for years.

Reviewed By: yfeldblum

Differential Revision: D9846361

fbshipit-source-id: ad28ff12fe16deb0ceee50ce6c098f234e8f9692
parent 13deb457
find_path(LIBURCU_INCLUDE_DIR NAMES urcu.h)
mark_as_advanced(LIBURCU_INCLUDE_DIR)
find_library(LIBURCU_LIBRARY NAMES urcu)
mark_as_advanced(LIBURCU_LIBRARY)
include(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(
LIBURCU
REQUIRED_VARS LIBURCU_LIBRARY LIBURCU_INCLUDE_DIR)
if(LIBURCU_FOUND)
set(LIBURCU_LIBRARIES ${LIBURCU_LIBRARY})
set(LIBURCU_INCLUDE_DIRS ${LIBURCU_INCLUDE_DIR})
endif()
......@@ -135,10 +135,6 @@ find_package(LibAIO)
list(APPEND FOLLY_LINK_LIBRARIES ${LIBAIO_LIBRARIES})
list(APPEND FOLLY_INCLUDE_DIRECTORIES ${LIBAIO_INCLUDE_DIRS})
find_package(LibURCU)
list(APPEND FOLLY_LINK_LIBRARIES ${LIBURCU_LIBRARIES})
list(APPEND FOLLY_INCLUDE_DIRECTORIES ${LIBURCU_INCLUDE_DIRS})
list(APPEND FOLLY_LINK_LIBRARIES ${CMAKE_DL_LIBS})
list(APPEND CMAKE_REQUIRED_LIBRARIES ${CMAKE_DL_LIBS})
......
......@@ -163,15 +163,6 @@ if (NOT FOLLY_USE_SYMBOLIZER)
${FOLLY_DIR}/SingletonStackTrace.cpp
)
endif()
if (NOT ${LIBURCU_FOUND})
list(REMOVE_ITEM files
${FOLLY_DIR}/experimental/RCUUtils.cpp
)
list(REMOVE_ITEM hfiles
${FOLLY_DIR}/experimental/RCURefCount.h
${FOLLY_DIR}/experimental/RCUUtils.h
)
endif()
if (NOT ${LIBAIO_FOUND})
list(REMOVE_ITEM files
${FOLLY_DIR}/experimental/io/AsyncIO.cpp
......
/*
* Copyright 2015-present 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.
*/
#pragma once
#include <folly/ThreadLocal.h>
#include <folly/experimental/RCUUtils.h>
namespace folly {
class RCURefCount {
public:
using Int = int64_t;
RCURefCount()
: localCount_([&]() { return new LocalRefCount(globalCount_); }) {}
~RCURefCount() noexcept {
assert(state_ == State::GLOBAL);
assert(globalCount_.load() == 0);
}
// This can't increment from 0.
Int operator++() noexcept {
auto& localCount = *localCount_;
std::lock_guard<RCUReadLock> lg(RCUReadLock::instance());
auto state = state_.load();
if (LIKELY(state == State::LOCAL)) {
++localCount;
return 42;
} else if (state == State::GLOBAL_TRANSITION) {
++globalCount_;
return 42;
} else {
auto globalCount = globalCount_.load();
do {
if (!globalCount) {
return 0;
}
} while (
!globalCount_.compare_exchange_weak(globalCount, globalCount + 1));
return globalCount + 1;
}
}
Int operator--() noexcept {
auto& localCount = *localCount_;
std::lock_guard<RCUReadLock> lg(RCUReadLock::instance());
auto state = state_.load();
if (LIKELY(state == State::LOCAL)) {
--localCount;
return 42;
} else {
auto value = --globalCount_;
if (state == State::GLOBAL) {
assert(value >= 0);
return value;
} else {
return 42;
}
}
}
Int operator*() const {
std::lock_guard<RCUReadLock> lg(RCUReadLock::instance());
if (state_ == State::GLOBAL) {
return globalCount_;
}
return 42;
}
void useGlobal() noexcept {
std::array<RCURefCount*, 1> ptrs{{this}};
useGlobal(ptrs);
}
template <typename Container>
static void useGlobal(const Container& refCountPtrs) {
for (auto refCountPtr : refCountPtrs) {
refCountPtr->state_ = State::GLOBAL_TRANSITION;
}
synchronize_rcu();
// At this point everyone is using the global count
for (auto refCountPtr : refCountPtrs) {
auto accessor = refCountPtr->localCount_.accessAllThreads();
for (auto& count : accessor) {
count.collect();
}
refCountPtr->state_ = State::GLOBAL;
}
synchronize_rcu();
// After this ++ or -- can return 0.
}
private:
using AtomicInt = std::atomic<Int>;
enum class State {
LOCAL,
GLOBAL_TRANSITION,
GLOBAL,
};
class LocalRefCount {
public:
explicit LocalRefCount(AtomicInt& globalCount)
: count_(0), globalCount_(globalCount) {
RCURegisterThread();
}
~LocalRefCount() {
collect();
}
void collect() {
globalCount_ += count_;
count_ = 0;
}
void operator++() {
++count_;
}
void operator--() {
--count_;
}
private:
Int count_;
AtomicInt& globalCount_;
};
std::atomic<State> state_{State::LOCAL};
folly::ThreadLocal<LocalRefCount, RCURefCount> localCount_;
std::atomic<int64_t> globalCount_{1};
};
} // namespace folly
/*
* Copyright 2015-present 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 <folly/experimental/RCUUtils.h>
#include <folly/ThreadLocal.h>
namespace folly {
namespace {
struct RCURegisterThreadHelper {
RCURegisterThreadHelper() {
rcu_register_thread();
}
~RCURegisterThreadHelper() {
rcu_unregister_thread();
}
bool alive{false};
};
} // namespace
bool RCURegisterThread() {
static folly::ThreadLocal<RCURegisterThreadHelper>* rcuRegisterThreadHelper =
new folly::ThreadLocal<RCURegisterThreadHelper>();
auto& helper = **rcuRegisterThreadHelper;
auto ret = !helper.alive;
helper.alive = true;
return ret;
}
RCUReadLock& RCUReadLock::instance() {
// Both lock and unlock are static, so no need to worry about destruction
// order
static RCUReadLock instance;
return instance;
}
} // namespace folly
/*
* Copyright 2015-present 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.
*/
#pragma once
#include <urcu.h> // @manual
namespace folly {
/**
* This must be called at least once from any thread, which uses RCUReadLock.
* First call should happen before RCUReadLock is used for the first time. Can
* be safely called more that once.
*
* Returns true when called for the first time from current thread.
*/
bool RCURegisterThread();
class RCUReadLock {
public:
static RCUReadLock& instance();
static void lock() {
assert(RCURegisterThread() == false);
rcu_read_lock();
}
static void unlock() {
rcu_read_unlock();
}
private:
RCUReadLock() {}
};
} // namespace folly
......@@ -22,7 +22,6 @@
#include <folly/Benchmark.h>
#include <folly/Memory.h>
#include <folly/experimental/RCURefCount.h>
#include <folly/portability/GFlags.h>
template <
......@@ -51,10 +50,6 @@ void benchmark(size_t n) {
}
}
template <typename T>
using RCUMainPtr = folly::ReadMostlyMainPtr<T, folly::RCURefCount>;
template <typename T>
using RCUWeakPtr = folly::ReadMostlyWeakPtr<T, folly::RCURefCount>;
template <typename T>
using TLMainPtr = folly::ReadMostlyMainPtr<T, folly::TLRefCount>;
template <typename T>
......@@ -68,14 +63,6 @@ BENCHMARK(WeakPtrFourThreads, n) {
benchmark<std::shared_ptr, std::weak_ptr, 4>(n);
}
BENCHMARK(RCUReadMostlyWeakPtrOneThread, n) {
benchmark<RCUMainPtr, RCUWeakPtr, 1>(n);
}
BENCHMARK(RCUReadMostlyWeakPtrFourThreads, n) {
benchmark<RCUMainPtr, RCUWeakPtr, 4>(n);
}
BENCHMARK(TLReadMostlyWeakPtrOneThread, n) {
benchmark<TLMainPtr, TLWeakPtr, 1>(n);
}
......
......@@ -21,7 +21,6 @@
#include <thread>
#include <folly/Memory.h>
#include <folly/experimental/RCURefCount.h>
#include <folly/experimental/ReadMostlySharedPtr.h>
#include <folly/portability/GTest.h>
#include <folly/synchronization/Baton.h>
......@@ -66,7 +65,6 @@ class Coordinator {
}
void waitForRequest() {
folly::RCURegisterThread();
requestBaton_.wait();
}
......
......@@ -16,7 +16,6 @@
#include <thread>
#include <folly/Benchmark.h>
#include <folly/experimental/RCURefCount.h>
#include <folly/experimental/TLRefCount.h>
namespace folly {
......@@ -24,11 +23,6 @@ namespace folly {
template <typename Counter>
void shutdown(Counter&) {}
void shutdown(RCURefCount& c) {
c.useGlobal();
--c;
}
void shutdown(TLRefCount& c) {
c.useGlobal();
--c;
......@@ -58,22 +52,6 @@ void benchmark(size_t n) {
shutdown(x);
}
BENCHMARK(atomicOneThread, n) {
benchmark<std::atomic<RCURefCount::Int>, 1>(n);
}
BENCHMARK(atomicFourThreads, n) {
benchmark<std::atomic<RCURefCount::Int>, 4>(n);
}
BENCHMARK(RCURefCountOneThread, n) {
benchmark<RCURefCount, 1>(n);
}
BENCHMARK(RCURefCountFourThreads, n) {
benchmark<RCURefCount, 4>(n);
}
BENCHMARK(TLRefCountOneThread, n) {
benchmark<TLRefCount, 1>(n);
}
......
......@@ -15,7 +15,6 @@
*/
#include <thread>
#include <folly/experimental/RCURefCount.h>
#include <folly/experimental/TLRefCount.h>
#include <folly/portability/GTest.h>
#include <folly/synchronization/Baton.h>
......@@ -114,18 +113,10 @@ void stressTest(size_t itersCount) {
}
}
TEST(RCURefCount, Basic) {
basicTest<RCURefCount>();
}
TEST(TLRefCount, Basic) {
basicTest<TLRefCount>();
}
TEST(RCURefCount, Stress) {
stressTest<RCURefCount>(100000);
}
TEST(TLRefCount, Stress) {
// This is absurdly slow, so we can't
// do it that many times.
......
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