Skip to main content

WaitableHandle

Struct WaitableHandle 

Source
pub struct WaitableHandle { /* private fields */ }
Expand description

A handle the thread pool is able to wait on.

The pool does not support every waitable object: a mutex handle in particular produces undefined behaviour rather than an error. Requiring this type instead of a bare OwnedHandle moves that precondition from prose into the type system, so a safe caller cannot reach the undefined case.

Construct one safely from a win-sync-sys Event (From<Event>) or with WaitableHandle::event, or vouch for a handle obtained elsewhere with the narrow WaitableHandle::assume_waitable seam – WaitableHandle::assume_waitable_shared when the handle is shared with other holders, or WaitableHandle::assume_waitable_with when the handle needs a close routine other than CloseHandle. This mirrors UnassociatedEndpoint in windows-overlapped-io-sys, which pairs a safe open with an assume_overlapped escape hatch for the same reason.

Implementations§

Source§

impl WaitableHandle

Source

pub fn event(manual_reset: bool, initially_signalled: bool) -> Result<Self>

Create an event and wrap it as a waitable handle.

An event is always a supported wait target, so this needs no unsafe. A manual_reset event stays signalled until it is reset; an auto-reset event returns to unsignalled as soon as one wait is satisfied, which makes it the usual choice for handing off work one activation at a time.

The event is a win-sync-sys Event, so this crate creates none of its own. To be able to set the event once the wait holds it, create the Event directly, keep a clone, and convert the other with From<Event>: the two share one handle. A wait made by this function keeps the only Event, so into_handle returns its handle.

§Errors

Returns the error from Event::new.

Source

pub unsafe fn assume_waitable(handle: OwnedHandle) -> Self

Wrap a handle whose wait support the caller vouches for.

This is the extensibility seam for wait targets this crate cannot create itself – semaphores, waitable timers, processes, threads, console input, change notifications, and so on.

§Safety

The caller guarantees that:

  • the handle is a waitable object the thread pool supports, and in particular is not a mutex, which the SDK does not support and which yields undefined behaviour rather than an error; and
  • ownership transfers exclusively into the returned value, so nothing else closes the handle while a wait on it is pending.
Source

pub unsafe fn assume_waitable_with(handle: HANDLE, close: WaitCloseFn) -> Self

Wrap a handle that must be closed with a routine other than CloseHandle.

Some waitable objects have their own destructor: a FindFirstChangeNotification handle is closed with FindCloseChangeNotification, and handing it to assume_waitable – which takes a std OwnedHandle and therefore closes it with CloseHandle – would be wrong. close is invoked exactly once, and only after the wait has been drained, whether the object is torn down by ThreadpoolWait’s own drop or by a CleanupGroup release.

close has the shape Win32 close routines already have, so it can be passed directly with no wrapper.

§Safety

The caller guarantees that:

  • the handle is a waitable object the thread pool supports, and in particular is not a mutex, which the SDK does not support and which yields undefined behaviour rather than an error;
  • ownership transfers exclusively into the returned value, so nothing else closes the handle while a wait on it is pending; and
  • close is the correct destructor for this handle and is safe to call once on it after the pool has stopped watching it.
Source

pub unsafe fn assume_waitable_shared(handle: SharedHandle) -> Self

Wrap a shared handle whose wait support the caller vouches for.

The wait holds handle, one clone of a SharedHandle, and the caller may keep others: to signal the object, or to hand it to another waiter. The handle closes only when the last holder drops, so the clone the wait holds keeps it open for as long as the wait does, which is the guarantee assume_waitable gets from exclusive ownership.

§Safety

The caller guarantees that the handle is a waitable object the thread pool supports, and in particular is not a mutex, which the SDK does not support and which yields undefined behaviour rather than an error.

Source

pub fn handle(&self) -> BorrowedHandle<'_>

Borrow the underlying handle, for signalling or inspecting it.

Source

pub fn into_handle(self) -> Result<OwnedHandle, Self>

Consume the wrapper and recover the owned handle.

§Errors

Returns the wrapper back unchanged when it carries a custom close routine (see assume_waitable_with): an OwnedHandle closes what it holds with CloseHandle, which is precisely the wrong destructor for such a target, so there is no correct value to hand back. The handle is neither closed nor leaked – ownership simply stays where it was.

A shared target (see assume_waitable_shared) gives its handle back only as its last holder, as SharedHandle::try_into_owned does; while another holder remains, the wrapper is returned unchanged, still holding its clone.

Trait Implementations§

Source§

impl Debug for WaitableHandle

Source§

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

Formats the value using the given formatter. Read more
Source§

impl From<Event> for WaitableHandle

An event is always a target the pool supports, so this needs no unsafe.

An Event is guaranteed to be an event rather than a mutex – adopting a handle as one is unsafe in win-sync-sys for exactly this reason – and to carry the access a wait needs.

The target is shared: the wait holds the event’s handle with every clone of the Event the caller keeps, and the handle closes when the last of them drops.

A wait built this way is a shared target, so WaitableHandle::into_handle gives the handle back only when no clone of the Event remains, and returns the wrapper unchanged while one does. A caller that keeps a clone to signal the event therefore does not get the handle back from into_handle; it reaches the event through its clone.

Source§

fn from(event: Event) -> Self

Converts to this type from the input type.

Auto Trait Implementations§

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, !>

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.