about summary refs log tree commit diff
path: root/src/tools/miri/tests/pass/concurrency/spin_loop.rs
blob: 019bd44f164888fcf022fe1293c6515d265f13fa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
use std::sync::atomic::{AtomicUsize, Ordering};
use std::thread;

static FLAG: AtomicUsize = AtomicUsize::new(0);

fn spin() {
    let j = thread::spawn(|| {
        while FLAG.load(Ordering::Acquire) == 0 {
            // We do *not* yield, and yet this should terminate eventually.
        }
    });
    thread::yield_now(); // schedule the other thread
    FLAG.store(1, Ordering::Release);
    j.join().unwrap();
}

fn two_player_ping_pong() {
    static FLAG: AtomicUsize = AtomicUsize::new(0);

    let waiter1 = thread::spawn(|| {
        while FLAG.load(Ordering::Acquire) == 0 {
            // We do *not* yield, and yet this should terminate eventually.
        }
    });
    let waiter2 = thread::spawn(|| {
        while FLAG.load(Ordering::Acquire) == 0 {
            // We do *not* yield, and yet this should terminate eventually.
        }
    });
    let progress = thread::spawn(|| {
        FLAG.store(1, Ordering::Release);
    });
    // The first `join` blocks the main thread and thus takes it out of the equation.
    waiter1.join().unwrap();
    waiter2.join().unwrap();
    progress.join().unwrap();
}

fn main() {
    spin();
    two_player_ping_pong();
}