Skip to content

Instantly share code, notes, and snippets.

@RedBeard0531
Created April 14, 2018 20:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save RedBeard0531/5c24dbfcca71e7b611ecb3d504c7588b to your computer and use it in GitHub Desktop.
Save RedBeard0531/5c24dbfcca71e7b611ecb3d504c7588b to your computer and use it in GitHub Desktop.
Examples of broken release sequences
enum State {INIT, PHASE2, DONE};
std::atomic<State> state{INIT};
int non_atomic = 0; // placeholder for actual data.
auto phase1 = std::thread([&] {
non_atomic = 1;
state.store(PHASE2, std::memory_order_release);
auto phase2 = std::thread([&] {
// Note that the store of PHASE2 inter-thread
// happens before the store of DONE because of
// http://eel.is/c++draft/thread.thread.constr#6
state.store(DONE, std::memory_order_relaxed);
});
// Do stuff.
phase2.join();
});
auto consumer = std::thread([&] {
while (state.load(std::memory_order_acquire) < PHASE2) {}
assert(non_atomic == 1); // This is a race today!
});
consumer.join();
phase1.join();
enum State {INIT, PHASE2, PHASE3, DONE};
std::atomic<State> state{INIT};
int non_atomic = 0; // placeholder for actual data.
std::mutex mx;
std::condition_variable cv;
auto phase1 = std::thread([&] {
non_atomic = 1;
std::unique_lock lk(mx);
state.store(PHASE2, std::memory_order_release);
cv.notify_all();
});
auto phase2 = std::thread([&] {
std::unique_lock lk(mx);
// relaxed is safe here because the mutex synchronizes the phases
cv.wait(lk, [&] {
return state.load(std::memory_order_relaxed) == PHASE2;
});
// Do stuff.
state.store(PHASE3, std::memory_order_relaxed);
cv.notify_all();
});
auto phase3 = std::thread([&] {
std::unique_lock lk(mx);
cv.wait(lk, [&] {
return state.load(std::memory_order_relaxed) == PHASE3;
});
// Do stuff, then release final result.
state.store(DONE, std::memory_order_release);
cv.notify_all();
});
auto consumer = std::thread([&] {
while (state.load(std::memory_order_acquire) < PHASE2) {}
assert(non_atomic == 1); // This is a race today!
});
consumer.join();
phase1.join();
phase2.join();
phase3.join();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment