-
-
Notifications
You must be signed in to change notification settings - Fork 2.5k
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
No good way to reliably notify all consumers about a change #3757
Comments
This is not possible because unlike the channels, the |
Would changing signature of struct Event {
occured: Arc<Mutex<bool>>,
notify: Notify,
}
impl Event {
fn set(&self) {
*self.occured.lock().unwrap() = true;
self.notify.notify_waiters();
}
fn wait(&self) -> impl Future<Output = ()> {
let guard = self.occured.lock().unwrap();
let wait = self.notify.notified();
let occured = *guard;
async move {
if occured {
return;
} else {
wait.await;
}
}
}
} |
Something like that works, and is very similar to Watch with no value. But |
Actually I'm wrong, |
The |
Is your feature request related to a problem? Please describe.
Consider an use-case where a producer wants to notify consumers about a change, even if they were doing something else at the time of the notification.
At first Notify and Notify::notify_waiters seem like a fit, but it's not. Because notify_waiters doesn't make the permit available for waiters that are not waiting at the time of the notification.
C: subscribe to S by cloning the Notify
P:
notifier.notify_waiters()
C:
notifier.notified().await
<<< waits even if the permit was provided aboveOption 1
One way to get the expected behavior is to use a broadcast channel with capacity of 1.
C: subscribe to S by calling
sender.subscribe()
P:
sender.send(())
C:
receiver.recv().await
<<< wakes up correctly, with eitherErr(Lagged(_))
orOk(())
This works but involves a a couple locks inside the Broadcast channel unnecessarily.
Option 2
A
Watch
works too but it's unergonomic to keep bothSender
andReceivers
around, as there's no equivalent tosubscribe()
Describe the solution you'd like
Option 1
Add
Notifier::notify_all
which will notify all existing waiters, not only the ones awaiting.Option 2
Consider exposing
Watch::subscribe
which already exists internally. With it this use case can be modeled ergonomically/performantly with aSender::subscribe()
+Receiver::changed().await
tokio/tokio/src/sync/watch.rs
Line 413 in d4075a4
Describe alternatives you've considered
See description above, which mentions 2 options, each with its set of drawbacks.
Additional context
I did find #3066 seems to describe a similar need but was closed with a partial(?) solution in the form of
Notifier::notify_awaiters
which only takes into account current waiters.The text was updated successfully, but these errors were encountered: