From 3d84a49c376067c67d878b6710adc9865d758c62 Mon Sep 17 00:00:00 2001 From: Ross Sullivan Date: Sat, 18 Jan 2025 23:26:47 +0900 Subject: [PATCH] docs: Documented Send and Sync requirements for Mutex + MutexGuard --- library/std/src/sync/poison/mutex.rs | 32 ++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/library/std/src/sync/poison/mutex.rs b/library/std/src/sync/poison/mutex.rs index 01ef71a187fec..fb43ada637543 100644 --- a/library/std/src/sync/poison/mutex.rs +++ b/library/std/src/sync/poison/mutex.rs @@ -181,10 +181,29 @@ pub struct Mutex { data: UnsafeCell, } -// these are the only places where `T: Send` matters; all other -// functionality works fine on a single thread. +/// `T` must be `Send` for a [`Mutex`] to be `Send` because it is possible to acquire +/// the owned `T` from the `Mutex` via [`into_inner`]. +/// +/// [`into_inner`]: Mutex::into_inner #[stable(feature = "rust1", since = "1.0.0")] unsafe impl Send for Mutex {} + +/// `T` must be `Send` for [`Mutex`] to be `Sync`. +/// This ensures that the protected data can be accessed safely from multiple threads +/// without causing data races or other unsafe behavior. +/// +/// [`Mutex`] provides mutable access to `T` to one thread at a time. However, it's essential +/// for `T` to be `Send` because it's not safe for non-`Send` structures to be accessed in +/// this manner. For instance, consider [`Rc`], a non-atomic reference counted smart pointer, +/// which is not `Send`. With `Rc`, we can have multiple copies pointing to the same heap +/// allocation with a non-atomic reference count. If we were to use `Mutex>`, it would +/// only protect one instance of `Rc` from shared access, leaving other copies vulnerable +/// to potential data races. +/// +/// Also note that it is not necessary for `T` to be `Sync` as `&T` is only made available +/// to one thread at a time if `T` is not `Sync`. +/// +/// [`Rc`]: crate::rc::Rc #[stable(feature = "rust1", since = "1.0.0")] unsafe impl Sync for Mutex {} @@ -211,8 +230,17 @@ pub struct MutexGuard<'a, T: ?Sized + 'a> { poison: poison::Guard, } +/// A [`MutexGuard`] is not `Send` to maximize platform portablity. +/// +/// On platforms that use POSIX threads (commonly referred to as pthreads) there is a requirement to +/// release mutex locks on the same thread they were acquired. +/// For this reason, [`MutexGuard`] must not implement `Send` to prevent it being dropped from +/// another thread. #[stable(feature = "rust1", since = "1.0.0")] impl !Send for MutexGuard<'_, T> {} + +/// `T` must be `Sync` for a [`MutexGuard`] to be `Sync` +/// because it is possible to get a `&T` from `&MutexGuard` (via `Deref`). #[stable(feature = "mutexguard", since = "1.19.0")] unsafe impl Sync for MutexGuard<'_, T> {}