123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106 |
- //! 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<T> {
- /// The inner value.
- inner: UnsafeCell<T>,
- /// 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<T>,
- }
- /// 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<T> Mutex<T> {
- /// Create a new mutex with some inner value.
- #[inline]
- pub const fn new(inner: T) -> Mutex<T> {
- 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<T> {
- // 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<T: Send> Send for Mutex<T> {}
- unsafe impl<T: Send> Sync for Mutex<T> {}
- #[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);
- }
- }
|