emerald_std/sync/spin/
lock.rs

1use core::{
2    hint,
3    sync::atomic::{AtomicBool, Ordering},
4};
5
6/// A raw spin lock, only provides `lock` and `unlock` and waiting for the lock
7///
8/// This is an unsafe lock, it doesn't have any protection against deadlocks, or multiple locking
9/// A safe wrappers are implemented with `Mutex` and `ReMutex`
10pub(super) struct Lock {
11    // we still use `bool` that is not cache aligned
12    // because this will change in the future to use os mutexes, and better synchronization methods
13    locked: AtomicBool,
14}
15
16impl Lock {
17    pub const fn new() -> Self {
18        Self {
19            locked: AtomicBool::new(false),
20        }
21    }
22
23    pub fn lock(&self) {
24        while !self.try_lock() {
25            while self.locked.load(Ordering::Relaxed) {
26                hint::spin_loop();
27            }
28        }
29    }
30
31    #[must_use]
32    #[inline(always)]
33    /// Try to lock the lock, returns true if successful
34    pub fn try_lock(&self) -> bool {
35        self.locked
36            .compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed)
37            .is_ok()
38    }
39
40    /// SAFETY: the caller must assure that there is only one accessor for this lock
41    ///         we don't want multiple unlocks, it doesn't make sense for this Lock (check `super::remutex::ReMutex`)
42    pub unsafe fn unlock(&self) {
43        self.locked.store(false, Ordering::Release);
44    }
45}