sync: consider exposing Semaphore::close
in public API
#3061
Labels
A-tokio
Area: The main tokio crate
C-feature-request
Category: A feature request.
E-easy
Call for participation: Experience needed to fix: Easy / not much
M-sync
Module: tokio/sync
Milestone
Is your feature request related to a problem? Please describe.
When updating
tower::buffer
to Tokio 0.3, it was necessary to replace the use of tokio's bounded MPSC channel with a re-implementation using the unbounded MPSC and Tokio's semaphore. This is because the bounded MPSC no longer exposespoll_ready
, and theready
method borrows the sender, so it can't be easily boxed for an unbounded lifetime. UsingSender::poll_ready
used to be sufficient to ensure that tasks waiting for the buffer service to become ready would be notified when the buffer worker terminates, because the senders would be woken on close.This doesn't work with the new approach using the semaphore, because the
Semaphore::acquire_owned
method requires theSemaphore
itself to beArc
ed. TheArc
is necessary to uphold the intrusive waitlist's safety invariants; as the semaphore cannot be dropped while there are still tasks in its waitlist. However, this means we can't drop it to notify the waiting tasks. Instead, we use the somewhat jankier approach of just adding a big pile of permits to the semaphore and hoping that callers don't continue trying to acquire permits from it. This isn't great, for that reason and because it's theoretically (although probably not practically) possible to leak tasks if the semaphore is close to the maximum number of permits.See tower-rs/tower#480 for details.
Describe the solution you'd like
The internal semaphore implementation has a
close
method, which does exactly what we'd want it to do:tokio/tokio/src/sync/batch_semaphore.rs
Lines 165 to 186 in 9097ae5
However, the public API semaphore type doesn't expose this for users to call. It would be nice if it did, for use cases like this.
Describe alternatives you've considered
Notify
alongside the semaphore to signal that the buffer has closed. However,Notify::notify_all
is also not public, so that's not a great option.I can't think of any arguments against adding
close
to the API except that it's good to stabilize as minimal an API surface as possible. It doesn't feel like a potential footgun (as long as the behavior is documented)...The text was updated successfully, but these errors were encountered: