tracing-mutex 0.3.2

Ensure deadlock-free mutexes by allocating in order, or else.
Documentation
//! Show what a crash looks like
//!
//! This shows what a traceback of a cycle detection looks like. It is expected to crash when run in
//! debug mode, because it might deadlock. In release mode, no tracing is used and the program may
//! do any of the following:
//!
//! - Return a random valuation of `a`, `b`, and `c`. The implementation has a race-condition by
//!   design. I have observed (4, 3, 6), but also (6, 3, 5).
//! - Deadlock forever.
//!
//! One can increase the SLEEP_TIME constant to increase the likelihood of a deadlock to occur. On
//! my machine, 1ns of sleep time gives about a 50/50 chance of the program deadlocking.
use std::thread;
use std::time::Duration;

use tracing_mutex::stdsync::Mutex;

fn main() {
    let a = Mutex::new(1);
    let b = Mutex::new(2);
    let c = Mutex::new(3);

    // Increase this time to increase the likelihood of a deadlock.
    const SLEEP_TIME: Duration = Duration::from_nanos(1);

    // Depending on random CPU performance, this section may deadlock, or may return a result. With
    // tracing enabled, the potential deadlock is always detected and a backtrace should be
    // produced.
    thread::scope(|s| {
        // Create an edge from a to b
        s.spawn(|| {
            let a = a.lock().unwrap();
            thread::sleep(SLEEP_TIME);
            *b.lock().unwrap() += *a;
        });

        // Create an edge from b to c
        s.spawn(|| {
            let b = b.lock().unwrap();
            thread::sleep(SLEEP_TIME);
            *c.lock().unwrap() += *b;
        });

        // Create an edge from c to a
        //
        // N.B. the program can crash on any of the three edges, as there is no guarantee which
        // thread will execute first. Nevertheless, any one of them is guaranteed to panic with
        // tracing enabled.
        s.spawn(|| {
            let c = c.lock().unwrap();
            thread::sleep(SLEEP_TIME);
            *a.lock().unwrap() += *c;
        });
    });

    println!(
        "{}, {}, {}",
        a.into_inner().unwrap(),
        b.into_inner().unwrap(),
        c.into_inner().unwrap()
    );
}