Skip to content

Instantly share code, notes, and snippets.

@nlyan
Created October 9, 2024 07:43
Show Gist options
  • Save nlyan/1652543c1cd8e8b6f1516ecebdaba897 to your computer and use it in GitHub Desktop.
Save nlyan/1652543c1cd8e8b6f1516ecebdaba897 to your computer and use it in GitHub Desktop.
#include <atomic>
#include <cstdint>
#include <thread>
#include <iostream>
struct SeqLockThing
{
std::atomic<std::uint64_t> begin_version = 0;
int a = 0;
int b = 0;
std::atomic<std::uint64_t> commit_version = 0;
};
void write_loop(SeqLockThing& thing, std::uint64_t seq)
{
for (auto i = 0; i < 100'000'000; ++i)
{
auto version = thing.begin_version.load(std::memory_order_relaxed);
version += 1;
thing.begin_version.store(version, std::memory_order_release);
thing.a = seq++;
thing.b = seq++;
std::atomic_thread_fence(std::memory_order_release);
thing.commit_version.store(version, std::memory_order_release);
}
}
void read_loop(SeqLockThing& thing)
{
int problems = 0;
uint64_t last_version = UINT64_MAX;
for (auto i = 0; i < 100'000'000; ++i)
{
auto bv = thing.begin_version.load(std::memory_order_acquire);
if (bv == last_version)
{
continue;
}
std::atomic_thread_fence(std::memory_order_acquire);
auto a = thing.a;
auto b = thing.b;
last_version = thing.commit_version.load(std::memory_order_acquire);
if (bv != last_version) {
continue;
}
if (b != (a + 1)) {
std::cout << "a = " << a << ", b = " << b << ", bv = "
<< bv << ", last_version = " << last_version << std::endl;
++problems;
}
if (problems >= 10) {
break;
}
}
}
int main()
{
SeqLockThing thing;
std::jthread writer1 ([&]() { write_loop(thing, 0); });
std::jthread reader1 ([&]() { read_loop(thing); });
writer1.join();
reader1.join();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment