Skip to content

Instantly share code, notes, and snippets.

@aary
Last active October 30, 2020 21:10
Show Gist options
  • Save aary/a14ae8d008e1d48a0f2d61582209f217 to your computer and use it in GitHub Desktop.
Save aary/a14ae8d008e1d48a0f2d61582209f217 to your computer and use it in GitHub Desktop.
namespace {
struct Storage {
std::atomic<std::uint64_t> futex_{0};
std::atomic<std::uint64_t> next_;
std::aligned_storage_t<48, 8> storage_;
};
template <typename Waiter>
void transferCurrentException(Waiter* waiter) {
assert(std::current_exception());
new (&waiter->storage_) std::exception_ptr{std::current_exception()};
waiter->futex_.store(1, std::memory_order_release);
}
template <template <typename> class Atom = std::atomic>
void concurrentExceptionPropagationStress(
int,
std::chrono::milliseconds) {
auto exceptions = std::vector<std::unique_ptr<Storage>>{};
exceptions.resize(1000000);
for (auto i = std::size_t{0}; i < exceptions.size(); ++i) {
exceptions[i] = std::make_unique<Storage>();
}
auto throwing = std::function<void(std::uint64_t)>{[&](auto counter) {
if (counter % 2) {
throw std::runtime_error{folly::to<std::string>(counter)};
}
}};
std::cout << "Started test" << std::endl;
auto writer = std::thread{[&]() {
for (auto i = std::size_t{0}; i < exceptions.size(); ++i) {
try {
std::this_thread::yield();
throwing(i);
} catch (...) {
transferCurrentException(exceptions.at(i).get());
continue;
}
exceptions.at(i)->futex_.store(2, std::memory_order_release);
}
}};
auto reader = std::thread{[&]() {
for (auto i = std::size_t{0}; i < exceptions.size(); ++i) {
auto value = std::uint64_t{};
while (!(value = exceptions.at(i)->futex_.load(std::memory_order_acquire))) {}
if (value == 1) {
try {
auto buf = reinterpret_cast<std::exception_ptr*>(&exceptions.at(i)->storage_);
auto ex = folly::launder(buf);
auto copy = std::move(*ex);
ex->exception_ptr::~exception_ptr();
std::rethrow_exception(std::move(copy));
} catch (std::exception& exc) {
assert(folly::to<std::uint64_t>(exc.what()) == i);
}
}
}
}};
reader.join();
writer.join();
}
} // namespace
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment