// For RCU, we mostly want to benchmark the readers (cause it's designed for
// very fast readers and occasional writers). We have a writer thread that
// runs nonstop until all other reader threads are done.
- static std::atomic_bool rcu_readers_done;
+ static std::atomic_uint rcu_readers_num;
// MicroLock
static size_t s_nMicroLockPassCount;
// MicroSpinLock
}
static void run_rcu_writer_sync() {
- while (!rcu_readers_done.load(std::memory_order_acquire)) {
- auto *old_data = rcu_data.load(std::memory_order_relaxed);
+ while (rcu_readers_num.load(std::memory_order_acquire) > 0) {
+ auto *old_data = rcu_data.load(std::memory_order_consume);
auto *new_data = new RcuData(*old_data);
new_data->d1++;
new_data->d2++;
- rcu_data.store(new_data, std::memory_order_relaxed);
+ rcu_data.store(new_data, std::memory_order_release);
folly::synchronize_rcu();
delete old_data;
std::this_thread::sleep_for(
}
static void run_rcu_writer_no_sync() {
- while (!rcu_readers_done.load(std::memory_order_acquire)) {
- auto *old_data = rcu_data.load(std::memory_order_relaxed);
+ while (rcu_readers_num.load(std::memory_order_acquire) > 0) {
+ auto *old_data = rcu_data.load(std::memory_order_consume);
auto *new_data = new RcuData(*old_data);
new_data->d1++;
new_data->d2++;
- rcu_data.store(new_data, std::memory_order_relaxed);
+ rcu_data.store(new_data, std::memory_order_release);
folly::rcu_retire(old_data);
std::this_thread::sleep_for(
std::chrono::milliseconds(s_nRcuWriterFrequency));
size_t sum = 0;
for (size_t count = 0; count < pass_count; count++) {
folly::rcu_reader g;
- auto *data = rcu_data.load(std::memory_order_relaxed);
+ auto *data = rcu_data.load(std::memory_order_consume);
sum += (data->d1 + data->d2);
}
- std::cout << "Reader done" << std::endl;
+ rcu_readers_num.fetch_sub(1, std::memory_order_release);
// Just want to simulate the reading.
EXPECT_GT(sum, 0);
}
template <typename WriterFunc>
static void FollyRcuThreading(WriterFunc writer_func) {
+ rcu_readers_num.store(s_nThreadCount - 1, std::memory_order_release);
+
+ std::unique_ptr<std::thread[]> threads(new std::thread[s_nThreadCount]);
// One of the threads is a writer.
- size_t reader_thrd_cnt = s_nThreadCount - 1;
- rcu_readers_done.store(false, std::memory_order_release);
- std::unique_ptr<std::thread[]> reader_threads(
- new std::thread[reader_thrd_cnt]);
- std::thread writer_thread(writer_func);
- for (size_t i = 0; i < reader_thrd_cnt; i++) {
- reader_threads[i] = std::thread(run_rcu_reader, s_nRcuReaderPassCount);
+ threads[0] = std::thread(writer_func);
+ for (size_t i = 1; i < s_nThreadCount; i++) {
+ threads[i] = std::thread(run_rcu_reader, s_nRcuReaderPassCount);
}
- for (size_t i = 0; i < reader_thrd_cnt; i++) {
- reader_threads[i].join();
+ for (size_t i = 0; i < s_nThreadCount; i++) {
+ threads[i].join();
}
- rcu_readers_done.store(true, std::memory_order_release);
- writer_thread.join();
}
template <typename SmallLockType>
size_t FollySyncTest_Parallel::locked_data;
std::atomic<RcuData*> FollySyncTest_Parallel::rcu_data;
-std::atomic_bool FollySyncTest_Parallel::rcu_readers_done;
+std::atomic_uint FollySyncTest_Parallel::rcu_readers_num;
size_t FollySyncTest_Parallel::s_nThreadCount;
size_t FollySyncTest_Parallel::s_nMicroLockPassCount;
size_t FollySyncTest_Parallel::s_nMicroSpinLockPassCount;