pub struct Signals<'a, S> { /* private fields */ }
Expand description
Signal state manager and event listener.
Signals
maintains the signal state of an Executor
. This consists of the raised signal set
and the wakeup signal set. Upon polling the future, the raised signal set is frozen to the
then-current value of the event mask, all bits in the wakeup signal set are removed from the
event mask (atomically), and the wakeup signal set is cleared. See also Step::poll()
for behavior when the wakeup signal set is zero. Current poll functions which are driven
by any of the raised signals will be attempted. If a poll function is not attempted or does
not yet resolve to an output then its signal mask will be OR-ed into the wakeup signal set.
The future won’t be polled again until a raised signal matches the wakeup signal set.
The type parameter S
is an EventMask
.
§Delayed signals
The executor will examine the event mask after polling the future to check for any
immediate updates. Since the raised signal set remains frozen during polling, any signal
raised by the future itself through Events
won’t become visible until this happens.
This also means that external events are not tested for until the future yields. As an
optimization for the first case, Signals::raise()
updates the raised signal set
immediately. Correct programs are not able to observe this behavior.
Implementations§
Source§impl<'a, S: EventMask> Signals<'a, S>
impl<'a, S: EventMask> Signals<'a, S>
Sourcepub fn bind(&self) -> Executor<'_>
pub fn bind(&self) -> Executor<'_>
Bind a new executor to this signal source.
The executor will be constructed with a waker that does nothing. It can be replaced
by calling Executor::with_waker()
.
Sourcepub fn raise(&self, signals: S)
pub fn raise(&self, signals: S)
Raise a signal set without delays.
This will perform the equivalent of [pending().raise(signals)
], but it will
also update the raised signal set. This prevents the “delayed signals” effect
that is shown above. Prefer raise()
if another branch of this future (such as
in [futures::join!()
] might benefit from this, otherwise use pending().raise()
.
It is impossible to visibly influence a well-behaved poll function by switching
between raise()
or pending().raise()
at any call site; this is a best-effort
optimization only.
Sourcepub async fn drive<T, E, F>(&self, signals: S, poll: F) -> Result<T, E>
pub async fn drive<T, E, F>(&self, signals: S, poll: F) -> Result<T, E>
Asynchronously drive a fallible poll function to completion
The future produced by this method checks on each poll whether any of the signals
in signals
is present in the raised signal set. If that is so, it invokes the poll
function. On first poll, this check is omitted, thus guaranteeing at least one call
to the poll function. If the poll function succeeds or fails with
nb::Error::Other
, the future completes immediately with that value. If the poll
function returns nb::Error::WouldBlock
, or if none of the signals in signals
is present in the raised signal sent, then signals
is added to the wakeup signal
set and the future pends.
poll()
must handle spurious calls gracefully. There is no guarantee that any of
the intended effects of any signal in signals
has actually taken place. poll()
may not block.
Sourcepub async fn drive_infallible<T, F>(&self, signals: S, poll: F) -> T
pub async fn drive_infallible<T, F>(&self, signals: S, poll: F) -> T
Asynchronously drive an infallible poll function to completion.
This is a variant of Signals::drive()
intended for cases where there is no
proper error type. Although drive(sig, poll).await.unwrap()
works the same, it
often requires explicit type annotations if poll
is a closure. This method should
be preferred in such cases, such as when poll
is just a wrapper around
some_option.ok_or(WouldBlock)
.