pub struct WaitCell { /* private fields */ }Expand description
An atomically registered Waker.
This cell stores the Waker of a single task. A Waker is stored in
the cell either by calling poll_wait, or by polling a wait
future. Once a task’s Waker is stored in a WaitCell, it can be woken
by calling wake on the WaitCell.
§Implementation Notes
This is inspired by the AtomicWaker type used in Tokio’s
synchronization primitives, with the following modifications:
- An additional bit of state is added to allow setting a “close” bit.
- A
WaitCellis always woken by value (for now). WaitCelldoes not handle unwinding, becausemaitakedoes not support unwinding
Implementations§
Source§impl WaitCell
impl WaitCell
Sourcepub fn poll_wait(&self, cx: &mut Context<'_>) -> Poll<Result<(), PollWaitError>>
pub fn poll_wait(&self, cx: &mut Context<'_>) -> Poll<Result<(), PollWaitError>>
Poll to wait on this WaitCell, consuming a stored wakeup or
registering the Waker from the provided Context to be woken by
the next wakeup.
Once a Waker has been registered, a subsequent call to wake will
wake that Waker.
§Returns
Poll::Pendingif theWakerwas registered. If this method returnsPoll::Pending, then the registeredWakerwill be woken by a subsequent call towake.Poll::Ready(Ok(()))if the cell was woken by a call towakewhile theWakerwas being registered.Poll::Ready(Err(PollWaitError::Closed))if theWaitCellhas been closed.Poll::Ready(Err(PollWaitError::Busy))if another task was concurrently registering itsWakerwith thisWaitCell.
Sourcepub fn wait(&self) -> Wait<'_> ⓘ
pub fn wait(&self) -> Wait<'_> ⓘ
Wait to be woken up by this cell.
§Returns
This future completes with the following values:
Ok(())if the future was woken by a call towakeor another task callingpoll_waitorwaiton thisWaitCell.Err(Closed)if the task was woken by a call toclose, or theWaitCellwas already closed.
Note: The calling task’s Waker is not registered until AFTER the
first time the returned Wait future is polled. This means that if a
call to wake occurs between when wait is called and when the
future is first polled, the future will not complete. If the caller is
responsible for performing an operation which will result in an eventual
wakeup, prefer calling subscribe before performing that operation
and .awaiting the Wait future returned by subscribe.
Sourcepub fn subscribe(&self) -> Subscribe<'_> ⓘ
pub fn subscribe(&self) -> Subscribe<'_> ⓘ
Eagerly subscribe to notifications from this WaitCell.
This method returns a Subscribe Future, which outputs a Wait
Future. Awaiting the Subscribe future will eagerly register the
calling task to be woken by this WaitCell, so that the returned
Wait future will be woken by any calls to wake (or close)
that occur between when the Subscribe future completes and when the
returned Wait future is .awaited.
This is primarily intended for scenarios where the task that waits on a
WaitCell is responsible for performing some operation that
ultimately results in the WaitCell being woken. If the task were to
simply perform the operation and then call wait on the WaitCell,
a potential race condition could occur where the operation completes and
wakes the WaitCell before the Wait future is first .awaited.
Using subscribe, the task can ensure that it is ready to be woken by
the cell before performing an operation that could result in it being
woken.
These scenarios occur when a wakeup is triggered by another thread/CPU
core in response to an operation performed in the task waiting on the
WaitCell, or when the wakeup is triggered by a hardware interrupt
resulting from operations performed in the task.
§Examples
use maitake_sync::WaitCell;
// Perform an operation that results in a concurrent wakeup, such as
// unmasking an interrupt.
fn do_something_that_causes_a_wakeup() {
// ...
}
static WAIT_CELL: WaitCell = WaitCell::new();
// Subscribe to notifications from the cell *before* calling
// `do_something_that_causes_a_wakeup()`, to ensure that we are
// ready to be woken when the interrupt is unmasked.
let wait = WAIT_CELL.subscribe().await;
// Actually perform the operation.
do_something_that_causes_a_wakeup();
// Wait for the wakeup. If the wakeup occurred *before* the first
// poll of the `wait` future had successfully subscribed to the
// `WaitCell`, we would still receive the wakeup, because the
// `subscribe` future ensured that our waker was registered to be
// woken.
wait.await.expect("WaitCell is not closed");