New paste Repaste Download
pub mod slop_mutex {
    use core::cell::UnsafeCell;
    use core::hint::spin_loop;
    use core::ops::{Deref, DerefMut};
    use core::sync::atomic::{AtomicBool, Ordering};
    pub struct SpinMutex<T> {
        locked: AtomicBool,
        data: UnsafeCell<T>,
    }
    // Safety: SpinMutex is Sync if T is Send.
    // We use AtomicBool to synchronize access to the UnsafeCell.
    unsafe impl<T: Send> Sync for SpinMutex<T> {}
    pub struct SpinMutexGuard<'a, T> {
        lock: &'a SpinMutex<T>,
    }
    impl<T> SpinMutex<T> {
        pub const fn new(data: T) -> Self {
            Self {
                locked: AtomicBool::new(false),
                data: UnsafeCell::new(data),
            }
        }
        pub fn lock(&self) -> SpinMutexGuard<'_, T> {
            // Attempt to swap false -> true.
            // If it fails, we "spin" (loop) until it succeeds.
            while self
                .locked
                .compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed)
                .is_err()
            {
                // Signal to the CPU that we are in a spin loop to save power/resources
                spin_loop();
            }
            SpinMutexGuard { lock: self }
        }
    }
    impl<'a, T> Deref for SpinMutexGuard<'a, T> {
        type Target = T;
        fn deref(&self) -> &Self::Target {
            // Safety: We hold the lock, so we have exclusive access to the data.
            unsafe { &*self.lock.data.get() }
        }
    }
    impl<'a, T> DerefMut for SpinMutexGuard<'a, T> {
        fn deref_mut(&mut self) -> &mut Self::Target {
            // Safety: We hold the lock, so we have exclusive access to the data.
            unsafe { &mut *self.lock.data.get() }
        }
    }
    impl<'a, T> Drop for SpinMutexGuard<'a, T> {
        fn drop(&mut self) {
            // Set the lock back to false.
            // Release ordering ensures our changes to the data are visible to the next locker.
            self.lock.locked.store(false, Ordering::Release);
        }
    }
}
use std::{thread, time::Duration};
fn main() {
    static SLOP_COUNTER: slop_mutex::SpinMutex<usize> = slop_mutex::SpinMutex::new(0);
    let handle = thread::spawn(|| {
        println!("I'm on the other thread...");
        for _ in 0..100000 {
            let mut guard = SLOP_COUNTER.lock();
            *guard += 1;
            thread::sleep(Duration::from_micros(1));
        }
        println!(
            "I finished 100000 counts, the current count is {}",
            *SLOP_COUNTER.lock()
        );
    });
    println!("And I'm Javert");
    for _ in 0..100000 {
        let mut guard = SLOP_COUNTER.lock();
        *guard += 1;
        thread::sleep(Duration::from_micros(1));
    }
    println!(
        "I finished 100000 counts, the current count is {}",
        *SLOP_COUNTER.lock()
    );
    _ = handle.join();
}
Filename: main.rs. Size: 3kb. View raw, , hex, or download this file.

This paste expires on 2026-09-08 20:47:18.407319+00:00. Pasted through web.