Skip to content

Add Sender::closed future #102

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

Merged
merged 7 commits into from
Jul 6, 2025
Merged

Add Sender::closed future #102

merged 7 commits into from
Jul 6, 2025

Conversation

xmakro
Copy link
Contributor

@xmakro xmakro commented Nov 10, 2024

This adds Sender::closed() similar to tokio::sync::mpsc::Sender::closed() (link).

@xmakro
Copy link
Contributor Author

xmakro commented Nov 29, 2024

@notgull would it be possible to merge this?

This feature is very useful in producer/consumer patterns for shutting down the producer without having to attempt a send. For example, when forwarding a stream to an async_channel, we want to shut down as soon as the async_channel was closed. Without this PR, we can only shut down after receiving from the stream and attempting to send to the async_channel.

@aldanor
Copy link

aldanor commented Apr 2, 2025

Would very much appreciate if maintainers could take a look at this PR (now that @notgull is away, perhaps @taiki-e?), this is a very useful QoL feature to have.

Thanks in advance!

Copy link
Collaborator

@taiki-e taiki-e left a comment

Choose a reason for hiding this comment

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

Thanks for the PR and sorry for the late review.

src/lib.rs Outdated
Comment on lines 1348 to 1351
// Check if the channel is closed.
if !this.sender.is_closed() {
// Channel is not closed yet - now start listening for notifications.
*this.listener = Some(this.sender.channel.closed_ops.listen());
Copy link
Collaborator

Choose a reason for hiding this comment

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

I have two questions on these lines:

  • Why does the previous listener have to be discarded each time and a new one created?
  • Wouldn't this order (check -> listen) cause a race condition? (ref)

Maybe the correct way here is to create the listener at Sender::closed and call only S::poll in this branch.

Copy link
Contributor Author

@xmakro xmakro Jul 4, 2025

Choose a reason for hiding this comment

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

Thanks for the thorough review and pointing out the race. I first tried following your suggestion and creating the listener in closed(), but if closed() is called after the last sender dropped, then the listener will not be triggered in this case, and the test fails in this line. Instead, I followed the code pattern in recv with the loop and optional listener creation. It avoids the race and only creates the listener once.

xmakro and others added 3 commits July 4, 2025 21:18
Co-authored-by: Taiki Endo <te316e89@gmail.com>
Co-authored-by: Taiki Endo <te316e89@gmail.com>
@taiki-e taiki-e merged commit b665e04 into smol-rs:master Jul 6, 2025
7 checks passed
@taiki-e taiki-e mentioned this pull request Jul 6, 2025
@taiki-e
Copy link
Collaborator

taiki-e commented Jul 6, 2025

Published in 2.5.0.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

3 participants