pub struct AssociatedEndpoint<'port> { /* private fields */ }Expand description
An overlapped endpoint bound to exactly one CompletionPort.
The endpoint owns its handle and borrows the port it is associated with, so
the port cannot be dropped while any endpoint still routes completions to it.
It is intentionally not Clone.
Implementations§
Source§impl AssociatedEndpoint<'_>
impl AssociatedEndpoint<'_>
Sourcepub unsafe fn ioctl<I: IoBuf, O: IoBufMut>(
&self,
code: u32,
input: I,
output: O,
) -> Result<Started<DeviceIoControlIo<I, O>, O>>
pub unsafe fn ioctl<I: IoBuf, O: IoBufMut>( &self, code: u32, input: I, output: O, ) -> Result<Started<DeviceIoControlIo<I, O>, O>>
Submit an overlapped DeviceIoControl with control code code.
Returns Started::Pending with a DeviceIoControlIo token that
recovers the output buffer and byte count from the operation’s
completion, or – only on an endpoint in
FILE_SKIP_COMPLETION_PORT_ON_SUCCESS mode, where a synchronous success
queues no packet – Started::Completed with the output buffer already
in hand.
input is the input buffer (empty for control codes that take none) and
output is the buffer the device writes its result into. Both are owned
buffers of the caller’s choosing, handed over for the operation’s life
and returned when it completes: nothing is copied and nothing is
allocated here.
§Errors
Returns io::ErrorKind::InvalidInput if either buffer is longer than
u32::MAX bytes, which the control code’s byte counts cannot express, or
any immediate failure from issuing the control operation.
§Safety
code’s input layout must be self-contained: the driver may read or
write only the bytes inside input and the output buffer, never memory
reached through a pointer embedded in input. Some control codes take an
input structure that carries raw pointers to separate buffers –
SCSI_PASS_THROUGH_DIRECT::DataBuffer is one – which this adapter neither
owns nor keeps alive. Because the operation outlives this call, such a
pointee could be freed while the driver is still using it. For such a code
the caller must keep every referenced buffer alive until the operation
completes; the adapter cannot, because it does not know the code’s layout.
This is why the generic raw-code seam is unsafe even though a
self-contained code (an FSCTL query, say) needs nothing more than owned
buffers.
Source§impl AssociatedEndpoint<'_>
impl AssociatedEndpoint<'_>
Sourcepub fn read<B: IoBufMut>(
&self,
buffer: B,
offset: u64,
) -> Result<Started<FileIo<B>, B>>
pub fn read<B: IoBufMut>( &self, buffer: B, offset: u64, ) -> Result<Started<FileIo<B>, B>>
Submit an overlapped read into buffer, starting at offset.
The buffer is any owned IoBufMut – a Vec<u8>, a Box<[u8]>, a
PageBuffers, or a caller’s own pooled or aligned type – handed over
for the operation’s life and returned when it completes. Nothing is
copied and nothing is allocated here: a caller that wants a fresh Vec
writes vec![0; n] at the call site, where the allocation is visible.
Returns Started::Pending with a FileIo token that recovers the
buffer and byte count from the operation’s completion, or – only on an
endpoint in FILE_SKIP_COMPLETION_PORT_ON_SUCCESS mode, where a
synchronous success queues no packet – Started::Completed with the
buffer already in hand.
§Errors
Returns io::ErrorKind::InvalidInput if the buffer is longer than
u32::MAX, or any immediate failure from issuing the read.
Sourcepub fn write<B: IoBuf>(
&self,
buffer: B,
offset: u64,
) -> Result<Started<FileIo<B>, B>>
pub fn write<B: IoBuf>( &self, buffer: B, offset: u64, ) -> Result<Started<FileIo<B>, B>>
Submit an overlapped write of buffer, starting at offset.
The buffer is any owned IoBuf – including a shared Arc<[u8]> or a
&'static [u8], neither of which can be a read destination – handed over
for the operation’s life and returned when it completes. Nothing is
copied.
Returns Started::Pending with a FileIo token, or
Started::Completed with the buffer already in hand when the endpoint
is in skip-on-success mode and the write completed synchronously.
§Errors
Returns io::ErrorKind::InvalidInput if the buffer is longer than
u32::MAX, or any immediate failure from issuing the write.
Source§impl AssociatedEndpoint<'_>
impl AssociatedEndpoint<'_>
Sourcepub fn read_scatter(
&self,
buffers: PageBuffers,
offset: u64,
) -> Result<Started<ScatterGatherIo, PageBuffers>>
pub fn read_scatter( &self, buffers: PageBuffers, offset: u64, ) -> Result<Started<ScatterGatherIo, PageBuffers>>
Submit an overlapped scatter-read into buffers, starting at offset.
Takes the caller’s pages rather than allocating fresh ones, so a pooled
or reused PageBuffers costs nothing to submit. The endpoint must be
opened with FILE_FLAG_NO_BUFFERING.
Returns Started::Pending with a ScatterGatherIo token, or
Started::Completed with the PageBuffers already in hand when the
endpoint is in skip-on-success mode and the read completed synchronously.
§Errors
Returns io::ErrorKind::InvalidInput if the pages total more than
u32::MAX bytes, or any immediate failure from issuing the
scatter-read.
Sourcepub fn write_gather(
&self,
buffers: PageBuffers,
offset: u64,
) -> Result<Started<ScatterGatherIo, PageBuffers>>
pub fn write_gather( &self, buffers: PageBuffers, offset: u64, ) -> Result<Started<ScatterGatherIo, PageBuffers>>
Submit an overlapped gather-write of buffers starting at offset.
Returns Started::Pending with a ScatterGatherIo token, or
Started::Completed with the PageBuffers already in hand when the
endpoint is in skip-on-success mode and the write completed
synchronously. The endpoint must be opened with
FILE_FLAG_NO_BUFFERING.
§Errors
Returns io::ErrorKind::InvalidInput if the buffers total more than
u32::MAX bytes, or any immediate failure from issuing the gather-write.
Source§impl<'port> AssociatedEndpoint<'port>
impl<'port> AssociatedEndpoint<'port>
Sourcepub fn handle(&self) -> BorrowedHandle<'_>
pub fn handle(&self) -> BorrowedHandle<'_>
Borrow the underlying handle for issuing native operations.
Sourcepub fn notification_modes(&self) -> NotificationModes
pub fn notification_modes(&self) -> NotificationModes
The completion-notification modes this endpoint carries, as declared before it was associated.
The adapters read this to classify a synchronous native success: with
crate::NotificationModes::skip_completion_port_on_success set, no
packet will arrive for one, so it is an Issued::Completed rather than
an Issued::Pending.
Sourcepub fn port(&self) -> &'port CompletionPort
pub fn port(&self) -> &'port CompletionPort
The completion port this endpoint is associated with.
Sourcepub fn outstanding(&self) -> usize
pub fn outstanding(&self) -> usize
How many operations submitted on this endpoint have not yet had their completion packet dequeued.
Unlike CompletionPort::outstanding, this is scoped to this endpoint
alone – what AssociatedEndpoint’s own blocking Drop waits on.
Sourcepub unsafe fn submit<P, F>(
&self,
operation: Operation<P>,
issue: F,
) -> Submitted<P>
pub unsafe fn submit<P, F>( &self, operation: Operation<P>, issue: F, ) -> Submitted<P>
Submit an owned operation on this endpoint.
issue performs the single native overlapped call using the endpoint’s
handle and the operation’s stable OVERLAPPED pointer. It classifies the
outcome as an Issued: Issued::Pending when a completion packet
will be delivered, or Issued::Completed when the call finished
synchronously and no packet will arrive – the state a handle in
FILE_SKIP_COMPLETION_PORT_ON_SUCCESS mode reports on synchronous
success. It returns Err for an immediate failure that yields no
completion.
On the pending path the operation’s storage is transferred to the kernel
and recovered later with Completion::claim. On the synchronous and
failure paths the operation is returned intact through Submitted so
its storage can be reused or inspected.
§Panics
Panics if this port already has a live operation registered at the new
operation’s storage address. That cannot happen through ordinary use –
operation owns freshly boxed storage – and indicates a defect in this
crate’s own bookkeeping rather than in the calling code. See
OperationRegistry::insert for the invariant involved.
§Safety
issue must start exactly one overlapped operation using the provided
OVERLAPPED pointer and no other storage, and must classify the outcome
correctly: Issued::Pending only when a completion packet will be
delivered to this endpoint’s port, Issued::Completed only when the
operation is already complete and no packet will arrive, and Err only
when the submission failed and no completion will arrive.
issue must not unwind: a panic out of it can leave an operation
registered with no completion coming, which makes rundown wait forever. A
closure that might panic must catch it and return Err.
P: 'static because submitting leaks the operation’s storage, to be
freed later through a thunk carrying no lifetime – see
Operation::into_overlapped.
Sourcepub fn cancel(&self, id: OperationId) -> Result<()>
pub fn cancel(&self, id: OperationId) -> Result<()>
Request cancellation of a single outstanding operation.
Cancellation is only a request: the operation still completes, typically
with ERROR_OPERATION_ABORTED, and that completion remains the point at
which its storage is reclaimed with Completion::claim.
The identity is checked against this port’s live operations first. An
identity whose operation has already completed is rejected with
io::ErrorKind::NotFound and no native call is made, even if another
operation has since been given the same storage address – so retaining
an identity too long can never cancel an unrelated operation.
§Errors
Returns io::ErrorKind::NotFound if id no longer names a live
operation, or the error from CancelIoEx if the native request fails.
Sourcepub fn cancel_all(&self) -> Result<()>
pub fn cancel_all(&self) -> Result<()>
Request cancellation of every outstanding operation on this endpoint.