safe-lock 0.1.4

A lock struct with a `const fn` constructor and no `unsafe` - ARCHIVED
Documentation
use core::time::Duration;
use safe_lock::SafeLock;
use std::sync::atomic::{AtomicBool, Ordering};

static _STATIC_SAFE_LOCK: SafeLock = SafeLock::new();

#[test]
fn default() {
    let lock = SafeLock::default();
    let _guard = lock.lock();
}

#[test]
fn sequential() {
    let lock = SafeLock::new();
    {
        let _guard = lock.lock();
    }
    {
        let _guard = lock.lock();
    }
}

#[test]
fn quick_unblock() {
    static LOCK: SafeLock = SafeLock::new();
    let before = std::time::Instant::now();
    std::thread::spawn(|| {
        let _guard = LOCK.lock();
        std::thread::sleep(Duration::from_millis(100));
    });
    std::thread::sleep(Duration::from_millis(50));
    let _guard = LOCK.lock();
    let elapsed = std::time::Instant::now().saturating_duration_since(before);
    assert!((100..150).contains(&elapsed.as_millis()), "{elapsed:?}");
}

#[test]
fn multiple_threads() {
    static LOCK: SafeLock = SafeLock::new();
    static FLAG: AtomicBool = AtomicBool::new(false);
    let mut join_handles = Vec::new();
    for _ in 0..10 {
        join_handles.push(std::thread::spawn(|| {
            for _ in 0..100 {
                let _guard = LOCK.lock();
                assert!(!FLAG.swap(true, Ordering::SeqCst));
                std::thread::sleep(Duration::from_millis(1));
                assert!(FLAG.swap(false, Ordering::SeqCst));
            }
        }));
    }
    for join_handle in join_handles.drain(..) {
        join_handle.join().unwrap();
    }
}