//! Synchronization primitives. use sys; use core::cell::UnsafeCell; use core::sync::atomic::{self, AtomicBool}; use core::ops; /// A mutual exclusive container. /// /// This assures that only one holds mutability of the inner value. To get the inner value, you /// need acquire the "lock". If you try to lock it while a lock is already held elsewhere, it will /// block the thread until the lock is released. pub struct Mutex { /// The inner value. inner: UnsafeCell, /// The lock boolean. /// /// This is true, if and only if the lock is currently held. locked: AtomicBool, } /// A mutex guard. /// /// This acts as the lock. pub struct MutexGuard<'a, T: 'a> { mutex: &'a Mutex, } /// Release the mutex. impl<'a, T> Drop for MutexGuard<'a, T> { #[inline] fn drop(&mut self) { self.mutex.locked.store(false, atomic::Ordering::SeqCst); } } impl<'a, T> ops::Deref for MutexGuard<'a, T> { type Target = T; #[inline] fn deref(&self) -> &T { unsafe { &*self.mutex.inner.get() } } } impl<'a, T> ops::DerefMut for MutexGuard<'a, T> { fn deref_mut(&mut self) -> &mut T { unsafe { &mut *self.mutex.inner.get() } } } impl Mutex { /// Create a new mutex with some inner value. #[inline] pub const fn new(inner: T) -> Mutex { Mutex { inner: UnsafeCell::new(inner), locked: AtomicBool::new(false), } } /// Lock this mutex. /// /// If another lock is held, this will block the thread until it is released. #[inline] pub fn lock(&self) -> MutexGuard { // Lock the mutex. #[cfg(not(feature = "unsafe_no_mutex_lock"))] while self.locked.compare_and_swap(false, true, atomic::Ordering::SeqCst) { // ,___, // {O,o} // |)``) // SRSLY? sys::yield_now(); } MutexGuard { mutex: self, } } } unsafe impl Send for Mutex {} unsafe impl Sync for Mutex {} #[cfg(test)] mod test { use super::*; #[test] fn test_mutex() { let mutex = Mutex::new(3); assert_eq!(*mutex.lock(), 3); *mutex.lock() = 4; assert_eq!(*mutex.lock(), 4); *mutex.lock() = 0xFF; assert_eq!(*mutex.lock(), 0xFF); } }