about summary refs log tree commit diff
path: root/library/std/src/sync
diff options
context:
space:
mode:
authorMara Bos <m-ou.se@m-ou.se>2020-09-24 16:03:20 +0200
committerMara Bos <m-ou.se@m-ou.se>2020-09-27 10:05:56 +0200
commit6f6336b4a187b03312b978703496ea0ee9020ec9 (patch)
tree977253e1012f07a7a7a60c24e14102be3b363469 /library/std/src/sync
parentc9e5e6a53aef5cd1b939ecfa18f56bdf5bf0451c (diff)
downloadrust-6f6336b4a187b03312b978703496ea0ee9020ec9.tar.gz
rust-6f6336b4a187b03312b978703496ea0ee9020ec9.zip
Split sys_common::Mutex in StaticMutex and MovableMutex.
The (unsafe) Mutex from sys_common had a rather complicated interface.
You were supposed to call init() manually, unless you could guarantee it
was neither moved nor used reentrantly.

Calling `destroy()` was also optional, although it was unclear if 1)
resources might be leaked or not, and 2) if destroy() should only be
called when `init()` was called.

This allowed for a number of interesting (confusing?) different ways to
use this Mutex, all captured in a single type.

In practice, this type was only ever used in two ways:

1. As a static variable. In this case, neither init() nor destroy() are
   called. The variable is never moved, and it is never used
   reentrantly. It is only ever locked using the LockGuard, never with
   raw_lock.

2. As a Boxed variable. In this case, both init() and destroy() are
   called, it will be moved and possibly used reentrantly.

No other combinations are used anywhere in `std`.

This change simplifies things by splitting this Mutex type into
two types matching the two use cases: StaticMutex and MovableMutex.

The interface of both new types is now both safer and simpler. The first
one does not call nor expose init/destroy, and the second one calls
those automatically in its new() and Drop functions. Also, the locking
functions of MovableMutex are no longer unsafe.
Diffstat (limited to 'library/std/src/sync')
-rw-r--r--library/std/src/sync/condvar.rs4
-rw-r--r--library/std/src/sync/mutex.rs30
2 files changed, 6 insertions, 28 deletions
diff --git a/library/std/src/sync/condvar.rs b/library/std/src/sync/condvar.rs
index 7e2155dae6f..1376d8ebe8f 100644
--- a/library/std/src/sync/condvar.rs
+++ b/library/std/src/sync/condvar.rs
@@ -553,8 +553,8 @@ impl Condvar {
         unsafe { self.inner.notify_all() }
     }
 
-    fn verify(&self, mutex: &sys_mutex::Mutex) {
-        let addr = mutex as *const _ as usize;
+    fn verify(&self, mutex: &sys_mutex::MovableMutex) {
+        let addr = mutex.raw() as *const _ as usize;
         match self.mutex.compare_and_swap(0, addr, Ordering::SeqCst) {
             // If we got out 0, then we have successfully bound the mutex to
             // this cvar.
diff --git a/library/std/src/sync/mutex.rs b/library/std/src/sync/mutex.rs
index a1703c731d4..e8f5a6f4294 100644
--- a/library/std/src/sync/mutex.rs
+++ b/library/std/src/sync/mutex.rs
@@ -166,12 +166,7 @@ use crate::sys_common::poison::{self, LockResult, TryLockError, TryLockResult};
 #[stable(feature = "rust1", since = "1.0.0")]
 #[cfg_attr(not(test), rustc_diagnostic_item = "mutex_type")]
 pub struct Mutex<T: ?Sized> {
-    // Note that this mutex is in a *box*, not inlined into the struct itself.
-    // Once a native mutex has been used once, its address can never change (it
-    // can't be moved). This mutex type can be safely moved at any time, so to
-    // ensure that the native mutex is used correctly we box the inner mutex to
-    // give it a constant address.
-    inner: Box<sys::Mutex>,
+    inner: sys::MovableMutex,
     poison: poison::Flag,
     data: UnsafeCell<T>,
 }
@@ -218,15 +213,11 @@ impl<T> Mutex<T> {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn new(t: T) -> Mutex<T> {
-        let mut m = Mutex {
-            inner: box sys::Mutex::new(),
+        Mutex {
+            inner: sys::MovableMutex::new(),
             poison: poison::Flag::new(),
             data: UnsafeCell::new(t),
-        };
-        unsafe {
-            m.inner.init();
         }
-        m
     }
 }
 
@@ -378,7 +369,6 @@ impl<T: ?Sized> Mutex<T> {
                 (ptr::read(inner), ptr::read(poison), ptr::read(data))
             };
             mem::forget(self);
-            inner.destroy(); // Keep in sync with the `Drop` impl.
             drop(inner);
 
             poison::map_result(poison.borrow(), |_| data.into_inner())
@@ -411,18 +401,6 @@ impl<T: ?Sized> Mutex<T> {
     }
 }
 
-#[stable(feature = "rust1", since = "1.0.0")]
-unsafe impl<#[may_dangle] T: ?Sized> Drop for Mutex<T> {
-    fn drop(&mut self) {
-        // This is actually safe b/c we know that there is no further usage of
-        // this mutex (it's up to the user to arrange for a mutex to get
-        // dropped, that's not our job)
-        //
-        // IMPORTANT: This code must be kept in sync with `Mutex::into_inner`.
-        unsafe { self.inner.destroy() }
-    }
-}
-
 #[stable(feature = "mutex_from", since = "1.24.0")]
 impl<T> From<T> for Mutex<T> {
     /// Creates a new mutex in an unlocked state ready for use.
@@ -509,7 +487,7 @@ impl<T: ?Sized + fmt::Display> fmt::Display for MutexGuard<'_, T> {
     }
 }
 
-pub fn guard_lock<'a, T: ?Sized>(guard: &MutexGuard<'a, T>) -> &'a sys::Mutex {
+pub fn guard_lock<'a, T: ?Sized>(guard: &MutexGuard<'a, T>) -> &'a sys::MovableMutex {
     &guard.lock.inner
 }