mutex.rs 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. use core::cell::UnsafeCell;
  2. use core::ops::{Deref, DerefMut};
  3. use core::sync::atomic::AtomicI32 as AtomicInt;
  4. use core::sync::atomic::Ordering::SeqCst;
  5. use core::sync::atomic;
  6. use platform::types::*;
  7. use platform::{Pal, Sys};
  8. pub const FUTEX_WAIT: c_int = 0;
  9. pub const FUTEX_WAKE: c_int = 1;
  10. pub struct Mutex<T> {
  11. lock: UnsafeCell<AtomicInt>,
  12. content: UnsafeCell<T>,
  13. }
  14. unsafe impl<T: Send> Send for Mutex<T> {}
  15. unsafe impl<T: Send> Sync for Mutex<T> {}
  16. impl<T> Mutex<T> {
  17. /// Create a new mutex
  18. pub const fn new(content: T) -> Self {
  19. Self {
  20. lock: UnsafeCell::new(AtomicInt::new(0)),
  21. content: UnsafeCell::new(content),
  22. }
  23. }
  24. /// Create a new mutex that is already locked. This is a more
  25. /// efficient way to do the following:
  26. /// ```rust
  27. /// let mut mutex = Mutex::new(());
  28. /// mutex.manual_lock();
  29. /// ```
  30. pub unsafe fn locked(content: T) -> Self {
  31. Self {
  32. lock: UnsafeCell::new(AtomicInt::new(1)),
  33. content: UnsafeCell::new(content),
  34. }
  35. }
  36. unsafe fn atomic(&self) -> &mut AtomicInt {
  37. &mut *self.lock.get()
  38. }
  39. /// Tries to lock the mutex, fails if it's already locked. Manual means
  40. /// it's up to you to unlock it after mutex. Returns the last atomic value
  41. /// on failure. You should probably not worry about this, it's used for
  42. /// internal optimizations.
  43. pub unsafe fn manual_try_lock(&self) -> Result<&mut T, c_int> {
  44. self.atomic().compare_exchange(0, 1, SeqCst, SeqCst)
  45. .map(|_| &mut *self.content.get())
  46. }
  47. /// Lock the mutex, returning the inner content. After doing this, it's
  48. /// your responsibility to unlock it after usage. Mostly useful for FFI:
  49. /// Prefer normal .lock() where possible.
  50. pub unsafe fn manual_lock(&self) -> &mut T {
  51. let mut last = 0;
  52. // First, try spinning for really short durations:
  53. for _ in 0..100 {
  54. atomic::spin_loop_hint();
  55. last = match self.manual_try_lock() {
  56. Ok(content) => return content,
  57. Err(value) => value,
  58. };
  59. }
  60. // We're waiting for a longer duration, so let's employ a futex.
  61. loop {
  62. // If the value is 1, set it to 2 to signify that we're waiting for
  63. // it to to send a FUTEX_WAKE on unlock.
  64. //
  65. // - Skip the atomic operation if the last value was 2, since it most likely hasn't changed.
  66. // - Skip the futex wait if the atomic operation says the mutex is unlocked.
  67. if last == 2 || self.atomic().compare_exchange(1, 2, SeqCst, SeqCst).unwrap_or_else(|err| err) == 2 {
  68. Sys::futex(self.atomic().get_mut(), FUTEX_WAIT, 2);
  69. }
  70. last = match self.manual_try_lock() {
  71. Ok(content) => return content,
  72. Err(value) => value,
  73. };
  74. }
  75. }
  76. /// Unlock the mutex, if it's locked.
  77. pub unsafe fn manual_unlock(&self) {
  78. if self.atomic().swap(0, SeqCst) == 2 {
  79. // At least one futex is up, so let's notify it
  80. Sys::futex(self.atomic().get_mut(), FUTEX_WAKE, 1);
  81. }
  82. }
  83. /// Tries to lock the mutex and returns a guard that automatically unlocks
  84. /// the mutex when it falls out of scope.
  85. pub fn try_lock(&self) -> Option<MutexGuard<T>> {
  86. unsafe {
  87. self.manual_try_lock().ok().map(|content| MutexGuard {
  88. mutex: self,
  89. content,
  90. })
  91. }
  92. }
  93. /// Locks the mutex and returns a guard that automatically unlocks the
  94. /// mutex when it falls out of scope.
  95. pub fn lock(&self) -> MutexGuard<T> {
  96. MutexGuard {
  97. mutex: self,
  98. content: unsafe { self.manual_lock() },
  99. }
  100. }
  101. }
  102. pub struct MutexGuard<'a, T: 'a> {
  103. mutex: &'a Mutex<T>,
  104. content: &'a mut T,
  105. }
  106. impl<'a, T> Deref for MutexGuard<'a, T> {
  107. type Target = T;
  108. fn deref(&self) -> &Self::Target {
  109. &self.content
  110. }
  111. }
  112. impl<'a, T> DerefMut for MutexGuard<'a, T> {
  113. fn deref_mut(&mut self) -> &mut Self::Target {
  114. self.content
  115. }
  116. }
  117. impl<'a, T> Drop for MutexGuard<'a, T> {
  118. fn drop(&mut self) {
  119. unsafe {
  120. self.mutex.manual_unlock();
  121. }
  122. }
  123. }