sync.rs 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. //! Synchronization primitives.
  2. use sys;
  3. use core::cell::UnsafeCell;
  4. use core::sync::atomic::{self, AtomicBool};
  5. use core::ops;
  6. /// A mutual exclusive container.
  7. ///
  8. /// This assures that only one holds mutability of the inner value. To get the inner value, you
  9. /// need acquire the "lock". If you try to lock it while a lock is already held elsewhere, it will
  10. /// block the thread until the lock is released.
  11. pub struct Mutex<T> {
  12. /// The inner value.
  13. inner: UnsafeCell<T>,
  14. /// The lock boolean.
  15. ///
  16. /// This is true, if and only if the lock is currently held.
  17. locked: AtomicBool,
  18. }
  19. /// A mutex guard.
  20. ///
  21. /// This acts as the lock.
  22. pub struct MutexGuard<'a, T: 'a> {
  23. mutex: &'a Mutex<T>,
  24. }
  25. /// Release the mutex.
  26. impl<'a, T> Drop for MutexGuard<'a, T> {
  27. #[inline]
  28. fn drop(&mut self) {
  29. self.mutex.locked.store(false, atomic::Ordering::SeqCst);
  30. }
  31. }
  32. impl<'a, T> ops::Deref for MutexGuard<'a, T> {
  33. type Target = T;
  34. #[inline]
  35. fn deref(&self) -> &T {
  36. unsafe {
  37. &*self.mutex.inner.get()
  38. }
  39. }
  40. }
  41. impl<'a, T> ops::DerefMut for MutexGuard<'a, T> {
  42. fn deref_mut(&mut self) -> &mut T {
  43. unsafe {
  44. &mut *self.mutex.inner.get()
  45. }
  46. }
  47. }
  48. impl<T> Mutex<T> {
  49. /// Create a new mutex with some inner value.
  50. #[inline]
  51. pub const fn new(inner: T) -> Mutex<T> {
  52. Mutex {
  53. inner: UnsafeCell::new(inner),
  54. locked: AtomicBool::new(false),
  55. }
  56. }
  57. /// Lock this mutex.
  58. ///
  59. /// If another lock is held, this will block the thread until it is released.
  60. #[inline]
  61. pub fn lock(&self) -> MutexGuard<T> {
  62. // Lock the mutex.
  63. #[cfg(not(feature = "unsafe_no_mutex_lock"))]
  64. while self.locked.compare_and_swap(false, true, atomic::Ordering::SeqCst) {
  65. // ,___,
  66. // {O,o}
  67. // |)``)
  68. // SRSLY?
  69. sys::yield_now();
  70. }
  71. MutexGuard {
  72. mutex: self,
  73. }
  74. }
  75. }
  76. unsafe impl<T: Send> Send for Mutex<T> {}
  77. unsafe impl<T: Send> Sync for Mutex<T> {}
  78. #[cfg(test)]
  79. mod test {
  80. use super::*;
  81. #[test]
  82. fn test_mutex() {
  83. let mutex = Mutex::new(3);
  84. assert_eq!(*mutex.lock(), 3);
  85. *mutex.lock() = 4;
  86. assert_eq!(*mutex.lock(), 4);
  87. *mutex.lock() = 0xFF;
  88. assert_eq!(*mutex.lock(), 0xFF);
  89. }
  90. }