Struct cros_async::sync::Condvar
source · #[repr(align(128))]pub struct Condvar {
state: AtomicUsize,
waiters: UnsafeCell<LinkedList<WaiterAdapter>>,
mu: UnsafeCell<usize>,
}
Expand description
A primitive to wait for an event to occur without consuming CPU time.
Condition variables are used in combination with a RwLock
when a thread wants to wait for some
condition to become true. The condition must always be verified while holding the RwLock
lock.
It is an error to use a Condvar
with more than one RwLock
while there are threads waiting on
the Condvar
.
§Examples
use std::sync::Arc;
use std::thread;
use std::sync::mpsc::channel;
use cros_async::{
block_on,
sync::{Condvar, RwLock},
};
const N: usize = 13;
// Spawn a few threads to increment a shared variable (non-atomically), and
// let all threads waiting on the Condvar know once the increments are done.
let data = Arc::new(RwLock::new(0));
let cv = Arc::new(Condvar::new());
for _ in 0..N {
let (data, cv) = (data.clone(), cv.clone());
thread::spawn(move || {
let mut data = block_on(data.lock());
*data += 1;
if *data == N {
cv.notify_all();
}
});
}
let mut val = block_on(data.lock());
while *val != N {
val = block_on(cv.wait(val));
}
Fields§
§state: AtomicUsize
§waiters: UnsafeCell<LinkedList<WaiterAdapter>>
§mu: UnsafeCell<usize>
Implementations§
source§impl Condvar
impl Condvar
sourcepub async fn wait<'g, T>(
&self,
guard: RwLockWriteGuard<'g, T>
) -> RwLockWriteGuard<'g, T>
pub async fn wait<'g, T>( &self, guard: RwLockWriteGuard<'g, T> ) -> RwLockWriteGuard<'g, T>
Block the current thread until this Condvar
is notified by another thread.
This method will atomically unlock the RwLock
held by guard
and then block the current
thread. Any call to notify_one
or notify_all
after the RwLock
is unlocked may wake up
the thread.
To allow for more efficient scheduling, this call may return even when the programmer
doesn’t expect the thread to be woken. Therefore, calls to wait()
should be used inside a
loop that checks the predicate before continuing.
Callers that are not in an async context may wish to use the block_on
method to block the
thread until the Condvar
is notified.
§Panics
This method will panic if used with more than one RwLock
at the same time.
§Examples
let mut ready = block_on(mu.lock());
while !*ready {
ready = block_on(cv.wait(ready));
}
sourcepub async fn wait_read<'g, T>(
&self,
guard: RwLockReadGuard<'g, T>
) -> RwLockReadGuard<'g, T>
pub async fn wait_read<'g, T>( &self, guard: RwLockReadGuard<'g, T> ) -> RwLockReadGuard<'g, T>
Like wait()
but takes and returns a RwLockReadGuard
instead.
fn add_waiter(&self, waiter: Arc<Waiter>, raw_rwlock: &RawRwLock)
sourcepub fn notify_one(&self)
pub fn notify_one(&self)
Notify at most one thread currently waiting on the Condvar
.
If there is a thread currently waiting on the Condvar
it will be woken up from its call to
wait
.
Unlike more traditional condition variable interfaces, this method requires a reference to
the RwLock
associated with this Condvar
. This is because it is inherently racy to call
notify_one
or notify_all
without first acquiring the RwLock
lock. Additionally, taking
a reference to the RwLock
here allows us to make some optimizations that can improve
performance by reducing unnecessary wakeups.
sourcepub fn notify_all(&self)
pub fn notify_all(&self)
Notify all threads currently waiting on the Condvar
.
All threads currently waiting on the Condvar
will be woken up from their call to wait
.
Unlike more traditional condition variable interfaces, this method requires a reference to
the RwLock
associated with this Condvar
. This is because it is inherently racy to call
notify_one
or notify_all
without first acquiring the RwLock
lock. Additionally, taking
a reference to the RwLock
here allows us to make some optimizations that can improve
performance by reducing unnecessary wakeups.