From 81a18e7a94b380bae6363479174ee82b6a66745f Mon Sep 17 00:00:00 2001 From: Cypher Date: Wed, 1 Jul 2026 23:07:55 -0400 Subject: [PATCH] document blocking guarantees for `std::sync` --- library/std/src/sync/mod.rs | 8 ++++++++ library/std/src/sync/mpmc/mod.rs | 19 +++++++++++++++---- library/std/src/sync/mpsc.rs | 19 ++++++++++++++----- 3 files changed, 37 insertions(+), 9 deletions(-) diff --git a/library/std/src/sync/mod.rs b/library/std/src/sync/mod.rs index 439b5b09a5ac0..5ac0ff2da9af5 100644 --- a/library/std/src/sync/mod.rs +++ b/library/std/src/sync/mod.rs @@ -164,6 +164,14 @@ //! [`Once`]: crate::sync::Once //! [`OnceLock`]: crate::sync::OnceLock //! [`RwLock`]: crate::sync::RwLock +//! +//! ## Blocking guarantees +//! +//! Methods that are documented not to block will never block for an unbounded length of time. +//! That is, they may internally block through platform primitives but still "behave" like they are non-blocking. This difference is invisible to most programs. +//! +//! This is only of note to platforms which disallow blocking, such as multithreaded WebAssembly on the main thread. +//! None of the implementations in `std::sync` are guaranteed to be (or remain) non-blocking in this regard. #![stable(feature = "rust1", since = "1.0.0")] diff --git a/library/std/src/sync/mpmc/mod.rs b/library/std/src/sync/mpmc/mod.rs index a687f39431697..a34eabbccb1fc 100644 --- a/library/std/src/sync/mpmc/mod.rs +++ b/library/std/src/sync/mpmc/mod.rs @@ -15,8 +15,9 @@ //! //! 1. An asynchronous, infinitely buffered channel. The [`channel`] function //! will return a `(Sender, Receiver)` tuple where all sends will be -//! **asynchronous** (they never block). The channel conceptually has an -//! infinite buffer. +//! **asynchronous** (they never block for space to become available; see +//! [`std::sync`] for precise guarantees on blocking.) The channel +//! conceptually has an infinite buffer. //! //! 2. A synchronous, bounded channel. The [`sync_channel`] function will //! return a `(Sender, Receiver)` tuple where the storage for pending @@ -26,6 +27,7 @@ //! channel where each sender atomically hands off a message to a receiver. //! //! [`send`]: Sender::send +//! [`std::sync`]: ../index.html#blocking-guarantees //! //! ## Disconnection //! @@ -374,6 +376,11 @@ impl Sender { /// If called on a zero-capacity channel, this method will wait for a receive /// operation to appear on the other side of the channel. /// + /// If called on an unbounded channel, this method will never block in order to wait for space to + /// become available. (See [`std::sync`] for precise guarantees on blocking.) + /// + /// [`std::sync`]: ../index.html#blocking-guarantees + /// /// # Examples /// /// ``` @@ -770,9 +777,11 @@ pub struct Iter<'a, T: 'a> { /// if the corresponding channel has hung up. /// /// This iterator will never block the caller in order to wait for data to -/// become available. Instead, it will return [`None`]. +/// become available. Instead, it will return [`None`]. (See [`std::sync`] for +/// precise guarantees on blocking.) /// /// [`try_iter`]: Receiver::try_iter +/// [`std::sync`]: ../index.html#blocking-guarantees /// /// # Examples /// @@ -917,7 +926,8 @@ impl Receiver { /// /// This method will never block the caller in order to wait for data to /// become available. Instead, this will always return immediately with a - /// possible option of pending data on the channel. + /// possible option of pending data on the channel. (See [`std::sync`] for precise + /// guarantees on blocking.) /// /// If called on a zero-capacity channel, this method will receive a message only if there /// happens to be a send operation on the other side of the channel at the same time. @@ -929,6 +939,7 @@ impl Receiver { /// (one for disconnection, one for an empty buffer). /// /// [`recv`]: Self::recv + /// [`std::sync`]: ../index.html#blocking-guarantees /// /// # Examples /// diff --git a/library/std/src/sync/mpsc.rs b/library/std/src/sync/mpsc.rs index b74f84ff465c0..ad74ac2248878 100644 --- a/library/std/src/sync/mpsc.rs +++ b/library/std/src/sync/mpsc.rs @@ -15,8 +15,9 @@ //! //! 1. An asynchronous, infinitely buffered channel. The [`channel`] function //! will return a `(Sender, Receiver)` tuple where all sends will be -//! **asynchronous** (they never block). The channel conceptually has an -//! infinite buffer. +//! **asynchronous** (they never block for space to become available; see +//! [`std::sync`] for precise guarantees on blocking.) The channel +//! conceptually has an infinite buffer. //! //! 2. A synchronous, bounded channel. The [`sync_channel`] function will //! return a `(SyncSender, Receiver)` tuple where the storage for pending @@ -26,6 +27,7 @@ //! channel where each sender atomically hands off a message to a receiver. //! //! [`send`]: Sender::send +//! [`std::sync`]: ../index.html#blocking-guarantees //! //! ## Disconnection //! @@ -228,9 +230,11 @@ pub struct Iter<'a, T: 'a> { /// if the corresponding channel has hung up. /// /// This iterator will never block the caller in order to wait for data to -/// become available. Instead, it will return [`None`]. +/// become available. Instead, it will return [`None`]. (See [`std::sync`] for +/// precise guarantees on blocking.) /// /// [`try_iter`]: Receiver::try_iter +/// [`std::sync`]: ../index.html#blocking-guarantees /// /// # Examples /// @@ -590,7 +594,10 @@ impl Sender { /// will be received. It is possible for the corresponding receiver to /// hang up immediately after this function returns [`Ok`]. /// - /// This method will never block the current thread. + /// This method will never block the caller in order to wait for space to + /// become available. (See [`std::sync`] for precise guarantees on blocking.) + /// + /// [`std::sync`]: ../index.html#blocking-guarantees /// /// # Examples /// @@ -798,7 +805,8 @@ impl Receiver { /// /// This method will never block the caller in order to wait for data to /// become available. Instead, this will always return immediately with a - /// possible option of pending data on the channel. + /// possible option of pending data on the channel. (See [`std::sync`] for + /// precise guarantees on blocking.) /// /// This is useful for a flavor of "optimistic check" before deciding to /// block on a receiver. @@ -807,6 +815,7 @@ impl Receiver { /// (one for disconnection, one for an empty buffer). /// /// [`recv`]: Self::recv + /// [`std::sync`]: ../index.html#blocking-guarantees /// /// # Examples ///