pub struct Operation<P> { /* private fields */ }Expand description
Stable storage for one overlapped operation.
P is the caller’s payload, for example a buffer or a descriptor array. The
crate never interprets it. The OVERLAPPED lives in an UnsafeCell because
the kernel writes to it through Operation::overlapped_ptr while the owner
holds only a shared reference.
Implementations§
Source§impl<P> Operation<P>
impl<P> Operation<P>
Sourcepub fn new(payload: P) -> Self
pub fn new(payload: P) -> Self
Create idle storage with a zeroed OVERLAPPED and the given payload.
Sourcepub fn state(&self) -> OperationState
pub fn state(&self) -> OperationState
Return the current lifecycle state.
Sourcepub fn set_state(&mut self, state: OperationState)
pub fn set_state(&mut self, state: OperationState)
Set the lifecycle state marker.
Sourcepub fn into_overlapped(self) -> *mut OVERLAPPEDwhere
P: 'static,
pub fn into_overlapped(self) -> *mut OVERLAPPEDwhere
P: 'static,
Consume the operation for submission, transferring ownership out and
returning its stable OVERLAPPED identity.
The returned pointer identifies the operation and must be handed to
exactly one native overlapped call. Recover the operation afterward with
Operation::from_overlapped when the payload type is known (as in a
completion), or with reclaim_overlapped when it is not (as during
rundown). This is the submission seam shared by the completion-port and
thread-pool backends.
P: 'static because this is the moment the storage is leaked. The box is
freed later through a type-erased thunk that carries no lifetime, by
whichever path reclaims it – a completion, or rundown – and nothing at
that point can prove a borrow inside P is still live. A payload holding
a &'a T would compile without this bound and could then have its Drop
run after 'a ended. The bound sits here, rather than on Operation
itself, because it is the leak that requires it: the blocking backend
drives an operation through &mut without ever leaking it, and correctly
needs neither this nor Send.
§Examples
An owned payload submits fine:
use windows_overlapped_io_sys::Operation;
let operation = Operation::new(vec![0_u8; 32]);
let overlapped = operation.into_overlapped();
// SAFETY: nothing was submitted against it, so this reclaims the
// storage exactly once and no completion can be outstanding.
unsafe { windows_overlapped_io_sys::reclaim_overlapped(overlapped) };A payload borrowing from the caller’s frame is rejected, rather than
having its Drop run later against an expired borrow:
use windows_overlapped_io_sys::Operation;
fn leak_a_borrow(bytes: &[u8]) -> *mut std::ffi::c_void {
let operation = Operation::new(bytes);
operation.into_overlapped().cast()
}Sourcepub unsafe fn from_overlapped(overlapped: *mut OVERLAPPED) -> Self
pub unsafe fn from_overlapped(overlapped: *mut OVERLAPPED) -> Self
Recover an operation previously submitted with Operation::into_overlapped.
§Safety
overlapped must have been returned by Operation::into_overlapped on
an Operation<P> of this exact type, and must be reclaimed exactly once.
Sourcepub fn payload_mut(&mut self) -> &mut P
pub fn payload_mut(&mut self) -> &mut P
Mutably borrow the payload.
Exclusive access proves no operation is in flight, so preparing or inspecting the payload here cannot race a kernel write.
Sourcepub fn into_payload(self) -> P
pub fn into_payload(self) -> P
Consume the storage and recover the payload.
Sourcepub fn set_offset(&mut self, offset: u64)
pub fn set_offset(&mut self, offset: u64)
Set the seek position for endpoints that use OVERLAPPED offsets.
Non-seekable endpoints such as pipes and sockets must leave the offset at its default of zero.
Sourcepub fn overlapped_ptr(&self) -> *mut OVERLAPPED
pub fn overlapped_ptr(&self) -> *mut OVERLAPPED
Return the stable pointer that identifies this operation to a backend.
The pointer is valid only while the storage stays put; a backend must pin the operation before submitting and must not free the storage until the matching completion has been observed.