pub fn queue_user_apc(
thread: impl AsHandle,
routine: impl FnOnce() + Send + 'static,
) -> Result<()>Expand description
Queue routine to run on thread the next time it waits alertably: QueueUserAPC.
What ends an alertable wait (Alertable::Yes) is an APC, and this is
how one is made. The routine runs on thread, inside whichever alertable wait or sleep it
next makes, before that wait returns WaitOutcome::Alerted; a
thread that never waits alertably never runs it. APCs queued to a thread run in the order they
were queued.
thread is any handle that lends itself, and must carry THREAD_SET_CONTEXT access, to queue,
and THREAD_QUERY_LIMITED_INFORMATION, to ask which process it belongs to: a
std::thread::JoinHandle carries both.
It must be a thread of this process. The routine is an address and a closure in this
process, which mean nothing in another, where delivering it would run whatever is at that
address. A thread of another process is refused, as io::ErrorKind::InvalidInput, before
anything is queued.
A thread that has not finished starting runs it as it starts. Windows delivers an APC queued
to a new thread when the thread begins, before it reaches the Rust runtime that
std::thread::spawn sets up around the closure it was given, so the routine runs outside that
runtime: std::thread::current there aborts the process (“current thread handle already
set”). Queue to a thread known to be running – one that has announced itself – unless the
routine touches nothing of the runtime.
The routine may never run. If the thread ends first, or never waits alertably, it stays queued and is not dropped, so what it captured is leaked; no error says so, because the call succeeded. A routine that must not be lost needs a thread known to wait alertably.
It runs in whatever context the thread is in when it makes the wait – possibly while the
thread holds locks or is inside a callback of the caller’s – so it must not assume the thread
is idle. A panic in it aborts the process, as a panic out of any extern "system" function does.
§Errors
Invalid handle for one that is not a thread, access denied for a thread handle without
THREAD_QUERY_LIMITED_INFORMATION or THREAD_SET_CONTEXT, io::ErrorKind::InvalidInput for a
thread of another process, and otherwise the error from QueueUserAPC. The routine is dropped,
unrun, when the call fails.