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
impl WaitableHandle
Sourcepub fn event(manual_reset: bool, initially_signalled: bool) -> Result<Self>
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.
Sourcepub unsafe fn assume_waitable(handle: OwnedHandle) -> Self
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.
Sourcepub unsafe fn assume_waitable_with(handle: HANDLE, close: WaitCloseFn) -> Self
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
closeis the correct destructor for this handle and is safe to call once on it after the pool has stopped watching it.
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.
Sourcepub fn handle(&self) -> BorrowedHandle<'_>
pub fn handle(&self) -> BorrowedHandle<'_>
Borrow the underlying handle, for signalling or inspecting it.
Sourcepub fn into_handle(self) -> Result<OwnedHandle, Self>
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
impl Debug for WaitableHandle
Source§impl From<Event> for WaitableHandle
An event is always a target the pool supports, so this needs no unsafe.
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.