diff --git a/library/std/src/sync/rwlock.rs b/library/std/src/sync/rwlock.rs index f7e133163a456..c283e4293ca2a 100644 --- a/library/std/src/sync/rwlock.rs +++ b/library/std/src/sync/rwlock.rs @@ -573,7 +573,7 @@ impl From for RwLock { } impl<'rwlock, T: ?Sized> RwLockReadGuard<'rwlock, T> { - /// Create a new instance of `RwLockReadGuard` from a `RwLock`. + /// Creates a new instance of `RwLockReadGuard` from a `RwLock`. /// /// # Safety /// @@ -964,9 +964,51 @@ impl<'a, T: ?Sized> RwLockWriteGuard<'a, T> { /// Downgrades a write-locked `RwLockWriteGuard` into a read-locked [`RwLockReadGuard`]. /// - /// Atomically changes the state of the [`RwLock`] from exclusive mode into shared mode. + /// This method will atomically change the state of the [`RwLock`] from exclusive mode into + /// shared mode. This means that it is impossible for a writing thread to get in between a + /// thread calling `downgrade` and the same thread reading whatever it wrote while it had the + /// [`RwLock`] in write mode. /// - /// FIXME MORE DOCS COMING SOON. + /// Note that since we have the `RwLockWriteGuard`, we know that the [`RwLock`] is already + /// locked for writing, so this method cannot fail. + /// + /// # Example + /// + /// ``` + /// #![feature(rwlock_downgrade)] + /// use std::sync::{Arc, RwLock, RwLockWriteGuard}; + /// + /// // The inner value starts as 0. + /// let rw = Arc::new(RwLock::new(0)); + /// + /// // Put the lock in write mode. + /// let mut main_write_guard = rw.write().unwrap(); + /// + /// let evil = rw.clone(); + /// let handle = std::thread::spawn(move || { + /// // This will not return until the main thread drops the `main_read_guard`. + /// let mut evil_guard = evil.write().unwrap(); + /// + /// assert_eq!(*evil_guard, 1); + /// *evil_guard = 2; + /// }); + /// + /// // After spawning the writer thread, set the inner value to 1. + /// *main_write_guard = 1; + /// + /// // Atomically downgrade the write guard into a read guard. + /// let main_read_guard = RwLockWriteGuard::downgrade(main_write_guard); + /// + /// // Since `downgrade` is atomic, the writer thread cannot have set the inner value to 2. + /// assert_eq!(*main_read_guard, 1, "`downgrade` was not atomic"); + /// + /// // Clean up everything now + /// drop(main_read_guard); + /// handle.join().unwrap(); + /// + /// let final_check = rw.read().unwrap(); + /// assert_eq!(*final_check, 2); + /// ``` #[unstable(feature = "rwlock_downgrade", issue = "128203")] pub fn downgrade(s: Self) -> RwLockReadGuard<'a, T> { let lock = s.lock; diff --git a/library/std/src/sys/sync/rwlock/teeos.rs b/library/std/src/sys/sync/rwlock/teeos.rs index becd3575a72cd..a8584346dd8bc 100644 --- a/library/std/src/sys/sync/rwlock/teeos.rs +++ b/library/std/src/sys/sync/rwlock/teeos.rs @@ -45,6 +45,6 @@ impl RwLock { #[inline] pub unsafe fn downgrade(&self) { // Since there is no difference between read-locked and write-locked on this platform, this - // function is a no-op. + // function is simply a no-op as only 1 reader can read - the original writer. } }