Skip to content

sync: improve the docs for recv_many #7201

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

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
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
17 changes: 11 additions & 6 deletions tokio/src/sync/mpsc/bounded.rs
Original file line number Diff line number Diff line change
Expand Up @@ -248,12 +248,17 @@ impl<T> Receiver<T> {
/// as specified by `limit`. If `limit` is zero, the function immediately
/// returns `0`. The return value is the number of values added to `buffer`.
///
/// For `limit > 0`, if there are no messages in the channel's queue, but
/// the channel has not yet been closed, this method will sleep until a
/// message is sent or the channel is closed. Note that if [`close`] is
/// called, but there are still outstanding [`Permits`] from before it was
/// closed, the channel is not considered closed by `recv_many` until the
/// permits are released.
/// For `limit > 0`: If there are no messages in the channels' queue initially,
/// `recv_many` will sleep until a first message is received. After that, it will
///
/// * Return when the number of received messages reaches `limit`.
/// * Return earlier when the channel is closed or no further messages area
/// available in the channel at the time. In these cases,
/// the number of received messages can be lower than `limit`.
///
Comment on lines +254 to +258
Copy link
Contributor

Choose a reason for hiding this comment

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

If I'm skimming this, I'm going to see "return when the number of received messages reaches limit" and I will get the wrong impression. I agree the current docs are bad, but I don't think this wording is good either.

Copy link
Author

Choose a reason for hiding this comment

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

Could you please give me a hint in which way the current wording isn't up to par? Otherwise I'm not sure in which direction to go with this. 😅

Copy link
Contributor

Choose a reason for hiding this comment

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

How about something like this?

Receives between 1 and `limit` messages into `buffer`.

This method is intended as a performance optimization for cases where
you wish to process messages in batches. The method may return less than
`limit` messages, so `recv_many` can *not* be used to receive a fixed
number of messages in one call.

This method waits until at least one message is available, and then
receives as many messages as it can into `buffer` efficiently. The
number of messages added to `buffer` is returned, and this number will
often be less than `limit` even if the channel is still open.

For non-zero values of `limit`, this method will never return `0` unless
the channel has been closed and there are no remaining messages in the
channel's queue. This indicates that no further values can ever be
received from this `Receiver`. The channel is closed when all senders
have been dropped, or when [`close`] is called.

Note that if [`close`] is called, but there are still outstanding
[`Permits`] from before it was closed, the channel is not considered
closed by `recv_many` until the permits are used or dropped.

The capacity of `buffer` is increased as needed.

Copy link
Author

Choose a reason for hiding this comment

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

Yup that looks also good. 👍 Just two things:

Does this

Receives between 1 and limit messages into buffer.

contradict this?

For non-zero values of limit, this method will never return 0 unless the channel has been closed and there are no remaining messages in the channel's queue.

Maybe it makes sense to word that first sentence differently and say

Receives between 0 and limit messages into buffer.


And my second point: I would like to be a bit more precise here.

..., and then receives as many messages as it can ...

If we explain here in which case no further messages are loaded into the buffer, we can also change this

The number of messages added to buffer is returned, and this number will often be less than limit even if the channel is still open.

to remove the "often" part as we've explained in which situation the function is returning before the limit of messages is reached. I think that would be an important addition to the docs.

My suggestion for that part would be:

This method waits until at least one message is available, and then receives as many messages as possible into buffer (either the number of received messages reaches limit or no more messages are available at the time). The number of messages added to buffer is returned, and this number can be less than limit even if the channel is still open.


Now that I formulated my suggestions I am still wondering how my original proposal was not up to par. 😅 I feel like I've tried more to explain what happens in which situation compared to your proposal. In turn you've added the more obvious disclaimer that this function should not be expected to receive a limit amount of messages. At the end of the day I'm happy with any improvement of the docs here, but I'm still curious. 😉

Also, if we go with your proposal, please let me know if I should incorporate your suggestions (and give credit in the commit message I guess?) or if you will take over the contribution. :)

/// Note that if [`close`] is called, but there are still outstanding [`Permits`]
/// from before it was closed, the channel is not considered closed by
/// `recv_many` until the permits are released.
///
/// For non-zero values of `limit`, this method will never return `0` unless
/// the channel has been closed and there are no remaining messages in the
Expand Down
20 changes: 14 additions & 6 deletions tokio/src/sync/mpsc/unbounded.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,13 +173,20 @@ impl<T> UnboundedReceiver<T> {
/// Receives the next values for this receiver and extends `buffer`.
///
/// This method extends `buffer` by no more than a fixed number of values
/// as specified by `limit`. If `limit` is zero, the function returns
/// immediately with `0`. The return value is the number of values added to
/// `buffer`.
/// as specified by `limit`. If `limit` is zero, the function immediately
/// returns `0`. The return value is the number of values added to `buffer`.
///
/// For `limit > 0`, if there are no messages in the channel's queue,
/// but the channel has not yet been closed, this method will sleep
/// until a message is sent or the channel is closed.
/// For `limit > 0`: If there are no messages in the channels' queue initially,
/// `recv_many` will sleep until a first message is received. After that, it will
///
/// * Return when the number of received messages reaches `limit`.
/// * Return earlier when the channel is closed or no further messages area
/// available in the channel at the time. In these cases,
/// the number of received messages can be lower than `limit`.
///
/// Note that if [`close`] is called, but there are still outstanding [`Permits`]
/// from before it was closed, the channel is not considered closed by
/// `recv_many` until the permits are released.
///
/// For non-zero values of `limit`, this method will never return `0` unless
/// the channel has been closed and there are no remaining messages in the
Expand All @@ -197,6 +204,7 @@ impl<T> UnboundedReceiver<T> {
/// channel.
///
/// [`close`]: Self::close
/// [`Permits`]: struct@crate::sync::mpsc::Permit
///
/// # Examples
///
Expand Down