compio_compat\sys/
windows.rs1use std::{
2 io,
3 os::windows::io::{AsRawHandle, FromRawHandle, OwnedHandle, RawHandle},
4 time::Duration,
5};
6
7use compio_driver::AsRawFd;
8use compio_runtime::Runtime;
9use windows_sys::Win32::{
10 Foundation::{WAIT_FAILED, WAIT_TIMEOUT},
11 System::Threading::{CreateEventW, INFINITE, SetEvent, WaitForMultipleObjects},
12};
13
14use crate::sys::Adapter;
15
16struct WindowsAdapter {
17 runtime: Runtime,
18}
19
20impl WindowsAdapter {
21 fn new(runtime: Runtime) -> io::Result<Self> {
22 Ok(Self { runtime })
23 }
24
25 async fn wait(&self, timeout: Option<Duration>) -> io::Result<()> {
26 let (sender, receiver) = futures_channel::oneshot::channel::<io::Result<()>>();
27 let event = unsafe { CreateEventW(std::ptr::null(), 0, 0, std::ptr::null()) };
28 if event.is_null() {
29 return Err(io::Error::last_os_error());
30 }
31 let event_handle = unsafe { OwnedHandle::from_raw_handle(event as RawHandle) };
32
33 let timeout = match timeout {
34 Some(timeout) => timeout.as_millis() as u32,
35 None => INFINITE,
36 };
37
38 struct EventGuard(OwnedHandle);
39
40 impl Drop for EventGuard {
41 fn drop(&mut self) {
42 unsafe { SetEvent(self.0.as_raw_handle()) };
43 }
44 }
45
46 let _event_handle = EventGuard(event_handle);
47 let event = event as usize;
48 let driver = self.runtime.as_raw_fd() as usize;
49 windows_threading::submit(move || {
50 let handles = [event as RawHandle, driver as RawHandle];
51 let res = unsafe { WaitForMultipleObjects(2, handles.as_ptr(), 0, timeout) };
52 let res = match res {
53 WAIT_FAILED => Err(io::Error::last_os_error()),
54 WAIT_TIMEOUT => Err(io::ErrorKind::TimedOut.into()),
55 _ => Ok(()),
56 };
57 sender.send(res).ok();
58 });
59 receiver
60 .await
61 .map_err(|_| io::ErrorKind::Interrupted.into())
62 .flatten()
63 }
64}
65
66macro_rules! impl_adapter {
67 ($(#[$($attr:meta)*])? $name:ident) => {
68 $(#[$($attr)*])?
69 pub struct $name(WindowsAdapter);
70
71 impl Adapter for $name {
72 fn new(runtime: Runtime) -> io::Result<Self> {
73 WindowsAdapter::new(runtime).map(Self)
74 }
75
76 async fn wait(&self, timeout: Option<Duration>) -> io::Result<()> {
77 self.0.wait(timeout).await
78 }
79
80 fn clear(&self) -> io::Result<()> {
81 Ok(())
82 }
83 }
84
85 impl std::ops::Deref for $name {
86 type Target = Runtime;
87
88 fn deref(&self) -> &Self::Target {
89 &self.0.runtime
90 }
91 }
92 };
93}
94
95#[cfg(feature = "tokio")]
96impl_adapter! {
97 TokioAdapter
99}
100
101#[cfg(feature = "futures")]
102impl_adapter! {
103 FuturesAdapter
105}