Skip to content

Instantly share code, notes, and snippets.

@oconnor663
Created April 2, 2019 22:28
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 oconnor663/5ff2453ba645ec6fa98d5091d7f35f36 to your computer and use it in GitHub Desktop.
Save oconnor663/5ff2453ba645ec6fa98d5091d7f35f36 to your computer and use it in GitHub Desktop.
relaxed atomics
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::mpsc::sync_channel;
use std::sync::{Arc, Barrier};
static MY_ORDERING: Ordering = Ordering::Relaxed;
static A: AtomicBool = AtomicBool::new(false);
static B: AtomicBool = AtomicBool::new(false);
fn main() {
let barrier = Arc::new(Barrier::new(3));
// Worker thread 1 sets A and then reads B.
let barrier_clone = barrier.clone();
let (sender1, receiver1) = sync_channel(0);
std::thread::spawn(move || loop {
barrier_clone.wait();
A.store(true, MY_ORDERING);
let read = B.load(MY_ORDERING);
sender1.send(read).unwrap();
});
// Worker thread 2 sets B and then reads A.
let barrier_clone = barrier.clone();
let (sender2, receiver2) = sync_channel(0);
std::thread::spawn(move || loop {
barrier_clone.wait();
B.store(true, MY_ORDERING);
let read = A.load(MY_ORDERING);
sender2.send(read).unwrap();
});
// The main thread intializes A and B, and then signals the worker threads
// by triggering the Barrier. It receives the read from each thread. If the
// result is sequentially consistent (at least one read is true), it
// repeats. But if the result is inconsistent (both reads are false), it
// prints and quits.
let mut count = 0u64;
loop {
count += 1;
A.store(false, MY_ORDERING);
B.store(false, MY_ORDERING);
barrier.wait();
let read1 = receiver1.recv().unwrap();
let read2 = receiver2.recv().unwrap();
if !read1 && !read2 {
println!("Inconsistent result after {} iterations!", count);
return;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment