async_io/os/windows.rs
1//! Functionality that is only available on Windows.
2
3use crate::reactor::{Reactor, Readable, Registration};
4use crate::Async;
5
6use std::future::Future;
7use std::io::{self, Result};
8use std::os::windows::io::{AsHandle, AsRawHandle, BorrowedHandle, OwnedHandle, RawHandle};
9use std::pin::Pin;
10use std::task::{Context, Poll};
11
12/// A waitable handle registered in the reactor.
13///
14/// Some handles in Windows are “waitable”, which means that they emit a “readiness” signal after some event occurs. This function can be used to wait for such events to occur on a handle. This function can be used in addition to regular socket polling.
15///
16/// Waitable objects include the following:
17///
18/// - Console inputs
19/// - Waitable events
20/// - Mutexes
21/// - Processes
22/// - Semaphores
23/// - Threads
24/// - Timer
25///
26/// This structure can be used to wait for any of these objects to become ready.
27///
28/// ## Implementation
29///
30/// The current implementation waits on the handle by registering it in the application-global
31/// Win32 threadpool. However, in the future it may be possible to migrate to an implementation
32/// on Windows 10 that uses a mechanism similar to [`MsgWaitForMultipleObjectsEx`].
33///
34/// [`MsgWaitForMultipleObjectsEx`]: https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-msgwaitformultipleobjectsex
35///
36/// ## Caveats
37///
38/// Read the documentation for the [`Async`](crate::Async) type for more information regarding the
39/// abilities and caveats with using this type.
40#[derive(Debug)]
41pub struct Waitable<T>(Async<T>);
42
43impl<T> AsRef<T> for Waitable<T> {
44 fn as_ref(&self) -> &T {
45 self.0.as_ref()
46 }
47}
48
49impl<T: AsHandle> Waitable<T> {
50 /// Create a new [`Waitable`] around a waitable handle.
51 ///
52 /// # Examples
53 ///
54 /// ```no_run
55 /// use std::process::Command;
56 /// use async_io::os::windows::Waitable;
57 ///
58 /// // Create a new process to wait for.
59 /// let mut child = Command::new("sleep").arg("5").spawn().unwrap();
60 ///
61 /// // Wrap the process in an `Async` object that waits for it to exit.
62 /// let process = Waitable::new(child).unwrap();
63 ///
64 /// // Wait for the process to exit.
65 /// # async_io::block_on(async {
66 /// process.ready().await.unwrap();
67 /// # });
68 /// ```
69 pub fn new(handle: T) -> Result<Self> {
70 Ok(Self(Async {
71 source: Reactor::get()
72 .insert_io(unsafe { Registration::new_waitable(handle.as_handle()) })?,
73 io: Some(handle),
74 }))
75 }
76}
77
78impl<T: AsRawHandle> AsRawHandle for Waitable<T> {
79 fn as_raw_handle(&self) -> RawHandle {
80 self.get_ref().as_raw_handle()
81 }
82}
83
84impl<T: AsHandle> AsHandle for Waitable<T> {
85 fn as_handle(&self) -> BorrowedHandle<'_> {
86 self.get_ref().as_handle()
87 }
88}
89
90impl<T: AsHandle + From<OwnedHandle>> TryFrom<OwnedHandle> for Waitable<T> {
91 type Error = io::Error;
92
93 fn try_from(handle: OwnedHandle) -> Result<Self> {
94 Self::new(handle.into())
95 }
96}
97
98impl<T: Into<OwnedHandle>> TryFrom<Waitable<T>> for OwnedHandle {
99 type Error = io::Error;
100
101 fn try_from(value: Waitable<T>) -> std::result::Result<Self, Self::Error> {
102 value.into_inner().map(|handle| handle.into())
103 }
104}
105
106impl<T> Waitable<T> {
107 /// Get a reference to the inner handle.
108 pub fn get_ref(&self) -> &T {
109 self.0.get_ref()
110 }
111
112 /// Get a mutable reference to the inner handle.
113 ///
114 /// # Safety
115 ///
116 /// The underlying I/O source must not be dropped or moved out using this function.
117 pub unsafe fn get_mut(&mut self) -> &mut T {
118 self.0.get_mut()
119 }
120
121 /// Consumes the [`Waitable`], returning the inner handle.
122 pub fn into_inner(self) -> Result<T> {
123 self.0.into_inner()
124 }
125
126 /// Waits until the [`Waitable`] object is ready.
127 ///
128 /// This method completes when the underlying [`Waitable`] object has completed. See the documentation
129 /// for the [`Waitable`] object for more information.
130 ///
131 /// # Examples
132 ///
133 /// ```no_run
134 /// use std::process::Command;
135 /// use async_io::os::windows::Waitable;
136 ///
137 /// # futures_lite::future::block_on(async {
138 /// let child = Command::new("sleep").arg("5").spawn()?;
139 /// let process = Waitable::new(child)?;
140 ///
141 /// // Wait for the process to exit.
142 /// process.ready().await?;
143 /// # std::io::Result::Ok(()) });
144 /// ```
145 pub fn ready(&self) -> Ready<'_, T> {
146 Ready(self.0.readable())
147 }
148
149 /// Polls the I/O handle for readiness.
150 ///
151 /// When this method returns [`Poll::Ready`], that means that the OS has delivered a notification
152 /// that the underlying [`Waitable`] object is ready. See the documentation for the [`Waitable`]
153 /// object for more information.
154 ///
155 /// # Caveats
156 ///
157 /// Two different tasks should not call this method concurrently. Otherwise, conflicting tasks
158 /// will just keep waking each other in turn, thus wasting CPU time.
159 ///
160 /// # Examples
161 ///
162 /// ```no_run
163 /// use std::process::Command;
164 /// use async_io::os::windows::Waitable;
165 /// use futures_lite::future;
166 ///
167 /// # futures_lite::future::block_on(async {
168 /// let child = Command::new("sleep").arg("5").spawn()?;
169 /// let process = Waitable::new(child)?;
170 ///
171 /// // Wait for the process to exit.
172 /// future::poll_fn(|cx| process.poll_ready(cx)).await?;
173 /// # std::io::Result::Ok(()) });
174 /// ```
175 pub fn poll_ready(&self, cx: &mut Context<'_>) -> Poll<Result<()>> {
176 self.0.poll_readable(cx)
177 }
178}
179
180/// Future for [`Filter::ready`].
181#[must_use = "futures do nothing unless you `.await` or poll them"]
182#[derive(Debug)]
183pub struct Ready<'a, T>(Readable<'a, T>);
184
185impl<T> Future for Ready<'_, T> {
186 type Output = Result<()>;
187
188 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
189 Pin::new(&mut self.0).poll(cx)
190 }
191}