1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
//! A mutual exclusion primitive useful for protecting shared data.
//!
//! See [`Mutex`] for more details.
//!
//! [`Mutex`]: struct.Mutex.html

use core::cell::UnsafeCell;
use core::ops::{Deref, DerefMut};
use core::sync::atomic::AtomicBool;
use core::sync::atomic::Ordering::*;

/// A mutual exclusion primitive useful for protecting shared data.
///
/// This mutex supports only [`try_lock`] method, and hence never blocks.
///
/// [`try_lock`]: #method.try_lock
pub struct Mutex<T> {
  lock: AtomicBool,
  data: UnsafeCell<T>,
}

/// An RAII implementation of a "scoped lock" of a mutex. When this structure is
/// dropped (falls out of scope), the lock will be unlocked.
///
/// The data protected by the mutex can be accessed through this guard via its
/// `Deref` and `DerefMut` implementations.
///
/// This structure is created by the [`try_lock`] method on [`Mutex`].
///
/// [`Mutex`]: struct.Mutex.html
/// [`try_lock`]: struct.Mutex.html#method.try_lock
#[must_use]
pub struct MutexGuard<'a, T: 'a> {
  lock: &'a Mutex<T>,
}

unsafe impl<T: Send> Send for Mutex<T> {}
unsafe impl<T: Send> Sync for Mutex<T> {}

impl<'a, T> !Send for MutexGuard<'a, T> {}
unsafe impl<'a, T: Sync> Sync for MutexGuard<'a, T> {}

impl<T> Mutex<T> {
  /// Creates a new mutex in an unlocked state ready for use.
  ///
  /// # Examples
  ///
  /// ```
  /// use drone_core::sync::Mutex;
  ///
  /// let mutex = Mutex::new(0);
  /// ```
  #[inline(always)]
  pub const fn new(t: T) -> Self {
    Self {
      lock: AtomicBool::new(false),
      data: UnsafeCell::new(t),
    }
  }

  /// Attempts to acquire this lock.
  ///
  /// If the lock could not be acquired at this time, then `None` is returned.
  /// Otherwise, a RAII guard is returned. The lock will be unlocked when the
  /// guard is dropped.
  ///
  /// # Examples
  ///
  /// ```
  /// use drone_core::sync::Mutex;
  ///
  /// let mutex = Mutex::new(1);
  ///
  /// match mutex.try_lock() {
  ///   Some(n) => assert_eq!(*n, 1),
  ///   None => unreachable!(),
  /// };
  /// ```
  #[inline(always)]
  pub fn try_lock(&self) -> Option<MutexGuard<T>> {
    if !self.lock.swap(true, Acquire) {
      Some(MutexGuard { lock: self })
    } else {
      None
    }
  }

  /// Consumes this mutex, returning the underlying data.
  ///
  /// # Examples
  ///
  /// ```
  /// use drone_core::sync::Mutex;
  ///
  /// let mutex = Mutex::new(0);
  /// assert_eq!(mutex.into_inner(), 0);
  /// ```
  #[inline(always)]
  pub fn into_inner(self) -> T {
    let Self { data, .. } = self;
    unsafe { data.into_inner() }
  }

  /// Returns a mutable reference to the underlying data.
  ///
  /// Since this call borrows the `Mutex` mutably, no actual locking needs to
  /// take place --- the mutable borrow statically guarantees no locks exist.
  ///
  /// # Examples
  ///
  /// ```
  /// use drone_core::sync::Mutex;
  ///
  /// let mut mutex = Mutex::new(0);
  /// *mutex.get_mut() = 10;
  /// assert_eq!(*mutex.try_lock().unwrap(), 10);
  /// ```
  #[inline(always)]
  pub fn get_mut(&mut self) -> &mut T {
    unsafe { &mut *self.data.get() }
  }
}

impl<T: Default> Default for Mutex<T> {
  /// Creates a `Mutex<T>`, with the `Default` value for T.
  #[inline(always)]
  fn default() -> Self {
    Mutex::new(Default::default())
  }
}

impl<'a, T> Deref for MutexGuard<'a, T> {
  type Target = T;

  #[inline(always)]
  fn deref(&self) -> &T {
    unsafe { &*self.lock.data.get() }
  }
}

impl<'a, T> DerefMut for MutexGuard<'a, T> {
  #[inline(always)]
  fn deref_mut(&mut self) -> &mut T {
    unsafe { &mut *self.lock.data.get() }
  }
}

impl<'a, T> Drop for MutexGuard<'a, T> {
  #[inline(always)]
  fn drop(&mut self) {
    self.lock.lock.store(false, Release);
  }
}