Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sync: elaborate on unbounded send not being async #2600

Merged
merged 4 commits into from
Jun 17, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 29 additions & 2 deletions tokio/src/sync/mpsc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,13 @@
//! is rejected and the task will be notified when additional capacity is
//! available. In other words, the channel provides backpressure.
//!
//! Unbounded channels are also available using the `unbounded_channel`
//! constructor.
//! This module provides two variants of the channel: A bounded and an unbounded
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit:

Suggested change
//! This module provides two variants of the channel: A bounded and an unbounded
//! This module provides two variants of the channel: a bounded and an unbounded

//! variant. The bounded variant has a limit on the number of messages that the
Comment on lines +13 to +14
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also, how about just

Suggested change
//! This module provides two variants of the channel: A bounded and an unbounded
//! variant. The bounded variant has a limit on the number of messages that the
//! This module provides two variants of the channel: bounded and unbounded.
//! The bounded variant has a limit on the number of messages that the

//! channel can store, and if this limit is reached, trying to send another
//! message will sleep until a message is received from the channel. An unbounded
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe

Suggested change
//! message will sleep until a message is received from the channel. An unbounded
//! message will wait until a message is received from the channel. An unbounded

rather than "sleep", for consistency?

//! channel has an infinite capacity, so the `send` method never does any kind of
//! sleeping. This makes the [`UnboundedSender`] usable from both synchronous and
//! asynchronous code.
//!
//! # Disconnection
//!
Expand All @@ -32,8 +37,30 @@
//! consumes the channel to completion, at which point the receiver can be
//! dropped.
//!
//! # Communicating between sync and async code
//!
//! When you want to communicate between synchronous and asynchronous code, there
//! are two situations to consider:
//!
//! **Bounded channel**: If you need a bounded channel, you should use a bounded
//! Tokio mpsc channel for both directions of communication. To call the async
Darksonn marked this conversation as resolved.
Show resolved Hide resolved
//! [`send`][bounded-send] or [`recv`][bounded-recv] methods in sync code, you
//! should use [`Handle::block_on`].
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe something like:

Suggested change
//! should use [`Handle::block_on`].
//! should use [`Handle::block_on`]. This is because the sender must be able to wait
//! for additional capacity when the channel is full. `Handle::block_on` allows a
//! synchronous caller to wait on an `async fn`.

(in general, I want to make sure all docs that state "you should do X" also explain why you should do that)

//!
//! **Unbounded channel**: You should use the kind of channel that matches where
//! the receiver is. So for sending a message _from async to sync_, you should
//! use [the standard library unbounded channel][std-unbounded] or
//! [crossbeam][crossbeam-unbounded]. Similarly, for sending a message _from sync
//! to async_, you should use a Tokio mpsc channel.
Darksonn marked this conversation as resolved.
Show resolved Hide resolved
//!
//! [`Sender`]: crate::sync::mpsc::Sender
//! [`Receiver`]: crate::sync::mpsc::Receiver
//! [bounded-send]: crate::sync::mpsc::Sender::send()
//! [bounded-recv]: crate::sync::mpsc::Receiver::recv()
//! [`UnboundedSender`]: crate::sync::mpsc::UnboundedSender
//! [`Handle::block_on`]: crate::runtime::Handle::block_on()
//! [std-unbounded]: std::sync::mpsc::channel
//! [crossbeam-unbounded]: https://docs.rs/crossbeam/*/crossbeam/channel/fn.unbounded.html

pub(super) mod block;

Expand Down
8 changes: 4 additions & 4 deletions tokio/src/sync/mpsc/unbounded.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,14 +163,14 @@ impl<T> UnboundedSender<T> {

/// Attempts to send a message on this `UnboundedSender` without blocking.
///
/// If the receive half of the channel is closed, either due to [`close`]
/// being called or the [`UnboundedReceiver`] having been dropped,
/// the function returns an error. The error includes the value passed to `send`.
///
/// This method is not marked async because sending a message to an unbounded channel
/// never requires any form of waiting. Because of this, the `send` method can be
/// used in both synchronous and asynchronous code without problems.
///
/// If the receive half of the channel is closed, either due to [`close`]
/// being called or the [`UnboundedReceiver`] having been dropped, this
/// function returns an error. The error includes the value passed to `send`.
///
/// [`close`]: UnboundedReceiver::close
/// [`UnboundedReceiver`]: UnboundedReceiver
pub fn send(&self, message: T) -> Result<(), SendError<T>> {
Expand Down