1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
// Copyright (c) 2026 Mike Grier
//! Asynchronous procedure calls: `QueueUserAPC`.
use io;
use ;
use ptr;
use ;
/// What is queued: a routine to run once, on the thread the APC is queued to.
type Routine = ;
/// Queue `routine` to run on `thread` the next time it waits alertably: `QueueUserAPC`.
///
/// What ends an alertable wait ([`Alertable::Yes`](crate::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`](crate::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.
/// Refuse a thread that is not this process's: a routine's address is only meaningful here.
/// [`queue_user_apc`] to the calling thread.
///
/// The routine runs in the next alertable wait the thread makes, which is what makes the wait's
/// [`Alerted`](crate::WaitOutcome::Alerted) ending reachable without a second thread.
///
/// # Errors
///
/// The error from `QueueUserAPC`, which for the calling thread arises only when the kernel cannot
/// allocate the APC; no test reaches it.
/// The APC routine: takes back what `queue` boxed, and runs it.
///
/// # Safety
///
/// `data` must be the pointer `queue` gave to a successful `QueueUserAPC`, which the kernel
/// delivers at most once.
unsafe extern "system"