pub struct Condvar(_);
Expand description
Condition variable (for async)
For background information about of the semantics of a condition
variable, see Wikipedia and/or std::sync::Condvar
.
Unlike std
’s condition variables, async-condvar-fair
’s do not
block the current thread, only the current async task. Also,
multiple condition variables may be freely used with multiple
different mutexes.
Like all condition variables, async-condvar-wait
’s may generate
spurious wakeups. After completing a wait, you must re-check the
actual condition in your data structure, not simply assume that it
must be ready for you.
Implementations
sourceimpl Condvar
impl Condvar
sourcepub fn wait_baton<G>(&'c self, guard: G) -> Waiter<'c, G> where
G: RelockMutexGuard,
pub fn wait_baton<G>(&'c self, guard: G) -> Waiter<'c, G> where
G: RelockMutexGuard,
Wait for someone to call notify_one
or notify_all
Atomically unlocks the mutex corresponding to guard
and starts
waiting for notify.
This is a future producing (G, Option<
Baton
<'c>>)
.
G
is a fresh guard for the mutex, which has been unlocked and
relocked.
baton
is a token representing an possible obligation to either
perform the actions that the caller of notify_one
is
expecting, or re-notify the condvar. See Baton
. baton
will be None
if the wakeup was the result of notify_all
.
sourcepub async fn wait<G>(&'c self, guard: G) -> <G as RelockMutexGuard>::JustGuard where
G: RelockMutexGuard,
pub async fn wait<G>(&'c self, guard: G) -> <G as RelockMutexGuard>::JustGuard where
G: RelockMutexGuard,
Wait for a notification; caller must worry about cancellation
Like wait_baton
but disposes
of the baton
right away on return.
Beware task cancellation when using with notify_one
and an async mutex
When wait
, notify_one
, and an async mutex, are combined,
notifications can easily be lost: perhaps a task calling wait
could be cancelled after being woken up by notify_one
, but
before doing the actual work. If that happens, probably no
other task will be signaled and the work would go undone.
So when using notify_one
, with an async mutex, it is probably
best to use wait_baton
.
async-condvar-fair
does guarantee that notify_one
will
ensure that at least one wait
call returns to its caller, (In
particular, if the wait
task is cancelled after being selected
by notify_one
, but before it manages to acquire the mutex, the
condvar will be re-notified.)
But, in async code it is difficult and error-prone to try to
avoid waiting. Any await
might result in task cancellaton,
and then if you’re not using wait_baton
, the notification will
be lost.
wait_baton
avoids this problem. notify_all
doesn’t suffer
from it because everyone is woken up anyway. If you are using a
sync mutex, there is no problem either, because you won’t be
await
ing while processing (ie, while holding the mutex) anyway.
sourcepub async fn wait_no_relock<G>(&'c self, guard: G) -> Option<Baton<'c>>
pub async fn wait_no_relock<G>(&'c self, guard: G) -> Option<Baton<'c>>
Wait for notification; caller will have to relock the mutex
Like wait_baton
but does not relock the mutex.
This can be used with any mutex guard type, even one for
which no impl of RelockMutexGuard
is available.
wait_no_relock
will first start waiting for notifications, and
then drop guard
(which, with a mutex guard, will unlock the
mutex). When wait_no_relock
completes, you will very probably
want to acquire the mutex again: with wait_no_relock
this must
be done separately.
Be sure to dispose
of the Option<
Baton
>
exactly iff
that is appropriate.
Deadlock hazard
There is no type restricton on guard
. It is important that
you pass the ownership of the actual mutex guard.
There is no way for the compiler to spot if you don’t.
If (for example) you pass &mut MutexGuard
,
you will fail to unlock the mutex, usually resulting in deadlock.
sourceimpl Condvar
impl Condvar
sourcepub fn notify_one(&self)
pub fn notify_one(&self)
Notify a waiting task (aka “signal”)
If there are any tasks in wait_baton
(or
wait_no_relock
), at least one of them will wake up and get
Some(
Baton
)
from wait_baton.
Likewise, if there are any tasks in wait
, at least one of
them will wake up and return. But if that task is cancelled
after wait
completss, the notification may be lost.
See wait
and Baton
for a discussion of the interaction
between task cancellation and notify_one
.
Notifications do not “stack” or “count”. Calling notify_one
several times might still wake up only one task.
sourceimpl Condvar
impl Condvar
sourcepub fn notify_all(&self)
pub fn notify_all(&self)
Notify all waiting tasks (aka “broadcast”)
Wake up all tasks currently in wait
, wait_baton
,
and wait_no_relock
,
Each the tasks in wait
and wait_baton
will start to try
to reacquire the mutex; they will then (in general) take turns
to return from wait
/wait_baton
with the mutex held.
All tasks will get None
rather than Some(
Baton
)
,
from wait_baton
or wait_no_relock
- even possibly tasks
which are in the process of waking up because of a previous call
to notify_one
.
sourceimpl Condvar
impl Condvar
sourcepub fn make_baton(&'c self) -> Baton<'c>
pub fn make_baton(&'c self) -> Baton<'c>
Make a baton directly, without waiting
This may be useful in unusual situations.
If the returned Baton
is simply dropped, this is the same as
notify_one
.
Trait Implementations
Auto Trait Implementations
impl !RefUnwindSafe for Condvar
impl Send for Condvar
impl Sync for Condvar
impl Unpin for Condvar
impl UnwindSafe for Condvar
Blanket Implementations
sourceimpl<T> BorrowMut<T> for T where
T: ?Sized,
impl<T> BorrowMut<T> for T where
T: ?Sized,
const: unstable · sourcefn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more
sourceimpl<T> Downcast for T where
T: Any,
impl<T> Downcast for T where
T: Any,
sourcefn into_any(self: Box<T, Global>) -> Box<dyn Any + 'static, Global>ⓘNotable traits for Box<W, Global>impl<W> Write for Box<W, Global> where
W: Write + ?Sized, impl<R> Read for Box<R, Global> where
R: Read + ?Sized, impl<I, A> Iterator for Box<I, A> where
I: Iterator + ?Sized,
A: Allocator, type Item = <I as Iterator>::Item;
fn into_any(self: Box<T, Global>) -> Box<dyn Any + 'static, Global>ⓘNotable traits for Box<W, Global>impl<W> Write for Box<W, Global> where
W: Write + ?Sized, impl<R> Read for Box<R, Global> where
R: Read + ?Sized, impl<I, A> Iterator for Box<I, A> where
I: Iterator + ?Sized,
A: Allocator, type Item = <I as Iterator>::Item;
W: Write + ?Sized, impl<R> Read for Box<R, Global> where
R: Read + ?Sized, impl<I, A> Iterator for Box<I, A> where
I: Iterator + ?Sized,
A: Allocator, type Item = <I as Iterator>::Item;
Convert Box<dyn Trait>
(where Trait: Downcast
) to Box<dyn Any>
. Box<dyn Any>
can
then be further downcast
into Box<ConcreteType>
where ConcreteType
implements Trait
. Read more
sourcefn into_any_rc(self: Rc<T>) -> Rc<dyn Any + 'static>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any + 'static>
Convert Rc<Trait>
(where Trait: Downcast
) to Rc<Any>
. Rc<Any>
can then be
further downcast
into Rc<ConcreteType>
where ConcreteType
implements Trait
. Read more
sourcefn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
Convert &Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &Any
’s vtable from &Trait
’s. Read more
sourcefn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
Convert &mut Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &mut Any
’s vtable from &mut Trait
’s. Read more
sourceimpl<T> DowncastSync for T where
T: Any + Send + Sync,
impl<T> DowncastSync for T where
T: Any + Send + Sync,
sourceimpl<A> DynCastExt for A
impl<A> DynCastExt for A
sourcefn dyn_cast<T>(
self
) -> Result<<A as DynCastExtHelper<T>>::Target, <A as DynCastExtHelper<T>>::Source> where
A: DynCastExtHelper<T>,
T: ?Sized,
fn dyn_cast<T>(
self
) -> Result<<A as DynCastExtHelper<T>>::Target, <A as DynCastExtHelper<T>>::Source> where
A: DynCastExtHelper<T>,
T: ?Sized,
Use this to cast from one trait object type to another. Read more
sourcefn dyn_upcast<T>(self) -> <A as DynCastExtAdvHelper<T, T>>::Target where
A: DynCastExtAdvHelper<T, T, Source = <A as DynCastExtAdvHelper<T, T>>::Target>,
T: ?Sized,
fn dyn_upcast<T>(self) -> <A as DynCastExtAdvHelper<T, T>>::Target where
A: DynCastExtAdvHelper<T, T, Source = <A as DynCastExtAdvHelper<T, T>>::Target>,
T: ?Sized,
Use this to upcast a trait to one of its supertraits. Read more
sourcefn dyn_cast_adv<F, T>(
self
) -> Result<<A as DynCastExtAdvHelper<F, T>>::Target, <A as DynCastExtAdvHelper<F, T>>::Source> where
A: DynCastExtAdvHelper<F, T>,
F: ?Sized,
T: ?Sized,
fn dyn_cast_adv<F, T>(
self
) -> Result<<A as DynCastExtAdvHelper<F, T>>::Target, <A as DynCastExtAdvHelper<F, T>>::Source> where
A: DynCastExtAdvHelper<F, T>,
F: ?Sized,
T: ?Sized,
sourcefn dyn_cast_with_config<C>(
self
) -> Result<<A as DynCastExtAdvHelper<<C as DynCastConfig>::Source, <C as DynCastConfig>::Target>>::Target, <A as DynCastExtAdvHelper<<C as DynCastConfig>::Source, <C as DynCastConfig>::Target>>::Source> where
C: DynCastConfig,
A: DynCastExtAdvHelper<<C as DynCastConfig>::Source, <C as DynCastConfig>::Target>,
fn dyn_cast_with_config<C>(
self
) -> Result<<A as DynCastExtAdvHelper<<C as DynCastConfig>::Source, <C as DynCastConfig>::Target>>::Target, <A as DynCastExtAdvHelper<<C as DynCastConfig>::Source, <C as DynCastConfig>::Target>>::Source> where
C: DynCastConfig,
A: DynCastExtAdvHelper<<C as DynCastConfig>::Source, <C as DynCastConfig>::Target>,
Use this to cast from one trait object type to another. With this method the type parameter is a config type that uniquely specifies which cast should be preformed. Read more