Skip to content

Commit

Permalink
Add stress test for atomic_shared_ptr
Browse files Browse the repository at this point in the history
Summary: None of the existing unit tests exercises the local -> global refcount transfer, which is the most critical part in `atomic_shared_ptr` in terms of correctness, so add a stress test that `load()`s the pointer enough times to trigger a transfer.

Reviewed By: dmm-fb

Differential Revision: D39927439

fbshipit-source-id: a8a50e33dd4afd1bd7bf0a2c309d92503bfb949c
  • Loading branch information
ot authored and facebook-github-bot committed Oct 1, 2022
1 parent ece9ed1 commit 0a3f724
Showing 1 changed file with 43 additions and 0 deletions.
43 changes: 43 additions & 0 deletions folly/concurrency/test/AtomicSharedPtrTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -205,4 +205,47 @@ TEST(AtomicSharedPtr, DeterministicTest) {
DSched::join(t);
}
}

TEST(AtomicSharedPtr, StressTest) {
constexpr size_t kExternalOffset = 0x2000;

atomic_shared_ptr<bool> ptr;
std::atomic<size_t> num_loads = 0;
std::atomic<size_t> num_stores = 0;

// DeterministicSchedule is too slow for the number of iterations required
// here, and we need a test that exercises the native atomics.
std::vector<std::thread> threads;
for (int tid = 0; tid < FLAGS_num_threads; ++tid) {
threads.emplace_back([&] {
shared_ptr<bool> v;
for (size_t i = 0; i < 16 * kExternalOffset; ++i) {
// Each time we've gone through a few local -> global batches, replace
// the pointer to contend with other load()s. This also does the first
// initialization, and a few threads may see nullptr for a while.
if (num_loads++ % (kExternalOffset * 2) == 0) {
auto newv = std::make_shared<bool>();
// Alternate between store and CAS.
if (num_stores++ % 2 == 0) {
ptr.store(std::move(newv), std::memory_order_release);
} else {
v = ptr.load(std::memory_order_relaxed);
ptr.compare_exchange_strong(
v,
std::move(newv),
std::memory_order_acq_rel,
std::memory_order_relaxed);
}
}
// Increments the local count and decrements the external one,
// eventually forcing a batch transfer.
v = ptr.load(std::memory_order_acquire);
}
});
}
for (auto& t : threads) {
t.join();
}
}

#endif // defined(__GLIBCXX__)

0 comments on commit 0a3f724

Please sign in to comment.