Skip to main content

Operation

Struct Operation 

Source
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>

Source

pub fn new(payload: P) -> Self

Create idle storage with a zeroed OVERLAPPED and the given payload.

Source

pub fn state(&self) -> OperationState

Return the current lifecycle state.

Source

pub fn set_state(&mut self, state: OperationState)

Set the lifecycle state marker.

Source

pub fn into_overlapped(self) -> *mut OVERLAPPED
where 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()
}
Source

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.

Source

pub fn payload(&self) -> &P

Borrow the payload.

Source

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.

Source

pub fn into_payload(self) -> P

Consume the storage and recover the payload.

Source

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.

Source

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.

Trait Implementations§

Source§

impl<P: Debug> Debug for Operation<P>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<P> !Freeze for Operation<P>

§

impl<P> !RefUnwindSafe for Operation<P>

§

impl<P> !Send for Operation<P>

§

impl<P> !Sync for Operation<P>

§

impl<P> Unpin for Operation<P>
where P: Unpin,

§

impl<P> UnsafeUnpin for Operation<P>
where P: UnsafeUnpin,

§

impl<P> UnwindSafe for Operation<P>
where P: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.