pub struct Registration<M = Local>where
M: Mode,{ /* private fields */ }Expand description
A source that a Runtime watches, and the handle to do its I/O through.
A registration holds its runtime, so a task that holds one keeps the runtime alive.
Implementations§
Source§impl<M> Registration<M>where
M: Mode,
impl<M> Registration<M>where
M: Mode,
Sourcepub fn poll_io<T>(
&self,
cx: &mut Context<'_>,
interest: Interest,
operation: impl FnMut() -> Result<T>,
) -> Poll<Result<T>>
pub fn poll_io<T>( &self, cx: &mut Context<'_>, interest: Interest, operation: impl FnMut() -> Result<T>, ) -> Poll<Result<T>>
Runs operation while the source of this registration is ready for interest, and retries
it when new readiness arrives.
Returns the first success of operation, a partial write included, or its first error other
than WouldBlock. A WouldBlock means the source was not
ready after all. In that case, this arranges for the waker of cx to be woken once it is,
and returns Poll::Pending. If the OS then refuses to watch the source for interest,
this returns that error instead.
A registration keeps one waker per interest for this, so only one operation at a time can
wait in each direction. If a second operation waits to read, for example, it replaces the
first one, which is then never woken. One reader and one writer can wait together. More of
either must take turns, for example behind a lock, or wait through
ready, which any number of tasks can do at once, and run their
operation once it completes.
This never spins while the source is not ready. Since the source is non-blocking, as
Runtime::register requires, it never blocks the thread
either.
Nor does it let a source that is always ready keep the thread from the other tasks. A poll
of a task, or of the future passed to block_on, may complete 128 I/O operations
through this and through AsyncIo, which counts them the same way.
The next one yields, and so does every one after it until the poll is over: this wakes the
task itself and returns Poll::Pending without running operation, which sends the task
to the back of the queue. The tasks queued before it have their turn then, and the reactor
has its own once the batch of polls the task is in is over. An operation that fails with
WouldBlock is not counted.
The budget belongs to the thread, not to the future. Whatever is polled inside the poll of
a task shares what is left of the task’s budget, a blocking executor of another crate
included. Such an executor polls again as soon as it is woken, inside the same poll of the
task, where its operation yields again, so once the budget is spent it never gets its
operation done. Its future has to run inside unconstrained,
which lifts the budget for each poll of it. Polled there, or outside the poll of any runtime
of this crate, this has no limit.
Sourcepub fn ready(&self, interest: Interest) -> Readiness<'_, M> ⓘ
pub fn ready(&self, interest: Interest) -> Readiness<'_, M> ⓘ
Waits until the source of this registration is ready for interest, without running any
operation on it.
Use this for I/O done some other way: through a library that the source is handed to, for example, or with an operation that should run once after the wait rather than on every poll.
The wait completes once the runtime finds the source ready for interest, or once a wait of
the runtime fails. Nothing else completes it. Its first poll only stores the waker, and a
poll for any other reason, such as another future in the same task, leaves it waiting.
Any number of these can wait at once, on one source and in one direction, alongside an
operation of poll_io. Readiness wakes them all. Dropping one
gives up its wait.
Readiness is only a hint: another task may take the bytes, or the room, first. A failed wait
of the runtime also ends every wait for readiness, so that each waiter tries its operation
and sees the result for itself. So an operation run after this completes must still expect
WouldBlock, and wait again when it gets one.
§Errors
Fails on its first poll if the OS refuses to watch the source for interest.