windows_threading/pool.rs
1use super::*;
2
3/// A `Pool` object represents a private thread pool with its own thread limits.
4///
5/// This is in contrast to the default, or shared, thread pool used by the crate's `submit` function
6/// as well as other code within the same process.
7pub struct Pool(Box<TP_CALLBACK_ENVIRON_V3>);
8
9impl Pool {
10 /// Creates a new `Pool` object.
11 pub fn new() -> Self {
12 let mut e = TP_CALLBACK_ENVIRON_V3 {
13 Version: 3,
14 CallbackPriority: TP_CALLBACK_PRIORITY_NORMAL,
15 Size: core::mem::size_of::<TP_CALLBACK_ENVIRON_V3>() as u32,
16 ..Default::default()
17 };
18
19 unsafe {
20 e.Pool = check(CreateThreadpool(core::ptr::null()));
21 e.CleanupGroup = check(CreateThreadpoolCleanupGroup());
22 }
23
24 // The `TP_CALLBACK_ENVIRON_V3` is boxed to ensure its memory address remains stable for the life of the `Pool` object.
25 Self(Box::new(e))
26 }
27
28 /// Sets the thread limits for the `Pool` object.
29 pub fn set_thread_limits(&self, min: u32, max: u32) {
30 unsafe {
31 check(SetThreadpoolThreadMinimum(self.0.Pool, min));
32 SetThreadpoolThreadMaximum(self.0.Pool, max);
33 }
34 }
35
36 /// Submits the closure to run on the `Pool`.
37 ///
38 /// The closure cannot outlive the `Pool` on which it runs.
39 pub fn submit<'a, F: FnOnce() + Send + 'a>(&'a self, f: F) {
40 // This is safe because the lifetime of the closure is bounded by the `Pool`.
41 unsafe {
42 try_submit(&*self.0, f);
43 }
44 }
45
46 /// Waits for all submissions to finish.
47 ///
48 /// Dropping the `Pool` will also wait for all submissions to finish.
49 pub fn join(&self) {
50 unsafe {
51 CloseThreadpoolCleanupGroupMembers(self.0.CleanupGroup, 0, core::ptr::null_mut());
52 }
53 }
54}
55
56impl Default for Pool {
57 fn default() -> Self {
58 Self::new()
59 }
60}
61
62unsafe impl Sync for Pool {}
63unsafe impl Send for Pool {}
64
65impl Drop for Pool {
66 fn drop(&mut self) {
67 // The `Pool` object cannot be dropped without waiting for all closures to complete, as their
68 // lifetimes are only guaranteed to be as long as the `Pool` object.
69 self.join();
70
71 unsafe {
72 CloseThreadpoolCleanupGroup(self.0.CleanupGroup);
73 CloseThreadpool(self.0.Pool);
74 }
75 }
76}