pub struct IoContext(/* private fields */);Expand description
Connection context shared with transport read and write tasks.
Transport implementations obtain buffers from this context, perform
nonblocking I/O, and return completion through
release_read_buf and
update_write_status. Their return value tells
the task whether to continue, pause until notified, or stop.
§Shutdown
A transport task runs until poll_read_ready or
poll_write_ready reports Readiness::Close or
Readiness::Terminate, or until a status update returns
IoTaskStatus::Stop. All of those imply that the connection is already
closing or closed.
Graceful shutdown runs in two phases. In the first the filters shut down
while both directions stay open. In the second, buffered output is drained
into the transport while the read side is paused;
Readiness::Close is reported only once nothing is left to write. A
single shutdown timeout bounds both phases. If it elapses during filter
shutdown, that phase is skipped and transport shutdown begins. If it
elapses during transport shutdown, the connection closes and any remaining
output is discarded.
So by the time the loop exits there is nothing left to drain, whether the
connection was shut down gracefully or terminated. A task must never attempt
a final flush on the way out; it should release the transport immediately
and report the outcome through stopped. The two variants
differ only in how the transport is released: Readiness::Close closes
both directions gracefully, while Readiness::Terminate skips the
graceful close so that an aborted connection stays distinguishable from one
that ended normally. Terminate is reported for an explicit
IoRef::terminate, and when Io is
dropped while output it accepted has not reached the transport, because the
filter chain goes away with it and that output can never be delivered. Every
other way a connection can end, an expired shutdown timeout included,
reports Close.
Implementations§
Source§impl IoContext
impl IoContext
Sourcepub fn shutdown_timeout(&self) -> Seconds
pub fn shutdown_timeout(&self) -> Seconds
Gets the configured shutdown timeout.
A backend whose own teardown can stall, such as one waiting for cancelled operations to complete, can bound it with this, as the graceful shutdown before it is bounded.
Sourcepub fn poll_read_ready(&self, cx: &mut Context<'_>) -> Poll<Readiness>
pub fn poll_read_ready(&self, cx: &mut Context<'_>) -> Poll<Readiness>
Checks readiness for read operations.
Resolves to Readiness::Ready, Readiness::Close or
Readiness::Terminate, or stays Pending. Reads continue through the
filter shutdown phase so that filters can complete theirs, and are
paused for the transport shutdown phase, so Close is resolved here
only once the connection is terminated.
A filter that is not ready while the io state allows reads pauses
them, see IoRef::is_read_filter_paused. The dispatcher is notified
when the pause starts and when it ends.
Sourcepub fn poll_write_ready(&self, cx: &mut Context<'_>) -> Poll<Readiness>
pub fn poll_write_ready(&self, cx: &mut Context<'_>) -> Poll<Readiness>
Checks readiness for write operations.
Resolves to Readiness::Ready, Readiness::Close or
Readiness::Terminate, or stays Pending. Unlike the read path this
reports Close at the end of a graceful shutdown as well, once buffered
output has been drained, so the task must not flush again.
A filter that is not ready while output is waiting pauses writes, see
IoRef::is_write_filter_paused. The dispatcher is notified when the
pause starts and when it ends.
Sourcepub fn stop(&self, e: Option<Error>)
pub fn stop(&self, e: Option<Error>)
Stops I/O processing without graceful filter shutdown.
Pending application work is not drained. Unlike
IoRef::terminate, this does not request an
aborted transport release: the transport observes
Readiness::Close and closes both directions gracefully. Call
stopped afterwards, once transport teardown has
actually finished.
Sourcepub fn take_read_buf(&self) -> BytesMut ⓘ
pub fn take_read_buf(&self) -> BytesMut ⓘ
Takes a buffer for the next transport read.
The returned buffer must be released exactly once through
release_read_buf, even when the read
fails or would otherwise stop the task.
This hands out a buffer of its own while the dispatcher still has input
to consume, because the read buffer is moved out of the io state until
it is released and the dispatcher would not find it. A transport whose
read completes without suspending can avoid that with
with_read_buf.
Sourcepub fn release_read_buf(
&self,
buf: BytesMut,
status: Poll<Result<usize>>,
) -> IoTaskStatus
pub fn release_read_buf( &self, buf: BytesMut, status: Poll<Result<usize>>, ) -> IoTaskStatus
Releases a transport read buffer and reports the read result.
This is the counterpart of take_read_buf; every
buffer it hands out must come back here exactly once.
Poll::Ready(Ok(n)) reports that n bytes were appended to buf.
Zero marks the transport read side as closed and invokes the read filter
chain once with no new bytes. This lets filters emit final buffered data
or report truncated input. Further transport reads are parked, but
buffered input remains decodable and the write side remains usable until
graceful shutdown. Poll::Ready(Err(_)) terminates the connection.
Poll::Pending returns the buffer after a nonblocking operation made no
progress or a submitted operation was canceled for reissue.
The returned IoTaskStatus instructs the read task to continue
immediately, pause until notified, or stop.
Sourcepub fn with_read_buf<F>(&self, f: F) -> IoTaskStatus
pub fn with_read_buf<F>(&self, f: F) -> IoTaskStatus
Reads into the read buffer in place and reports the read result.
This is the counterpart of take_read_buf and
release_read_buf for a transport whose
read completes without suspending. f reads into the buffer it is
given and reports the same status release_read_buf takes, with the
same meaning.
The buffer is not moved out of the io state for the duration of the
call, so no temporary buffer is taken from the pool and no append is
needed to put the result back. A transport that keeps the buffer across
a suspension point cannot use this: the buffer would be missing while
the dispatcher looks for input, so it must take one of its own through
take_read_buf instead.
f must not read from this io again. Nested read access is unsupported
and may terminate the connection or lose nested buffer changes.
Sourcepub fn with_write_dst<F, R>(&self, f: F) -> R
pub fn with_write_dst<F, R>(&self, f: F) -> R
Provides mutable access to the transport-facing write destination.
This holds the encoded bytes that are ready to be written out.
Pending filter output is processed before f is invoked. The transport
may write bytes out directly, or take ownership of pages and write them
later; any page it removes is counted as in-flight output until it is
either returned to this buffer or reported as written through
update_write_status.
§Panics
Panics if the closure accesses the transport-facing write buffer again.
Sourcepub fn update_write_status(&self, status: Result<usize>) -> IoTaskStatus
pub fn update_write_status(&self, status: Result<usize>) -> IoTaskStatus
Updates the write status.
Ok(n) reports that the write attempt completed without error and that
n bytes reached the peer; n is zero when the attempt moved nothing.
Any page the transport is still holding stays counted as outstanding
output, so it must either be returned to the write buffer or reported
here. An error terminates the connection. The returned
IoTaskStatus instructs the write task to continue, pause until
notified, or stop.