windows_future/
async_spawn.rs

1use super::*;
2use std::sync::Mutex;
3
4struct State<T: Async> {
5    result: Option<Result<T::Output>>,
6    completed: Option<T::CompletedHandler>,
7    completed_assigned: bool,
8}
9
10impl<T: Async> State<T> {
11    fn status(&self) -> AsyncStatus {
12        match &self.result {
13            None => AsyncStatus::Started,
14            Some(Ok(_)) => AsyncStatus::Completed,
15            Some(Err(_)) => AsyncStatus::Error,
16        }
17    }
18
19    fn error_code(&self) -> HRESULT {
20        match &self.result {
21            Some(Err(error)) => error.code(),
22            _ => HRESULT(0),
23        }
24    }
25
26    fn get_results(&self) -> Result<T::Output> {
27        match &self.result {
28            Some(result) => result.clone(),
29            None => Err(Error::from_hresult(HRESULT(0x8000000Eu32 as i32))), // E_ILLEGAL_METHOD_CALL
30        }
31    }
32}
33
34struct SyncState<T: Async>(Mutex<State<T>>);
35
36impl<T: Async> SyncState<T> {
37    fn new() -> Self {
38        Self(Mutex::new(State {
39            result: None,
40            completed: None,
41            completed_assigned: false,
42        }))
43    }
44
45    fn status(&self) -> AsyncStatus {
46        self.0.lock().unwrap().status()
47    }
48
49    fn error_code(&self) -> HRESULT {
50        self.0.lock().unwrap().error_code()
51    }
52
53    fn get_results(&self) -> Result<T::Output> {
54        self.0.lock().unwrap().get_results()
55    }
56
57    fn set_completed(&self, sender: &T, handler: Ref<'_, T::CompletedHandler>) -> Result<()> {
58        let mut guard = self.0.lock().unwrap();
59
60        if guard.completed_assigned {
61            Err(Error::from_hresult(HRESULT(0x80000018u32 as i32))) // E_ILLEGAL_DELEGATE_ASSIGNMENT
62        } else {
63            guard.completed_assigned = true;
64            let status = guard.status();
65            let handler = handler.ok()?;
66
67            if status == AsyncStatus::Started {
68                guard.completed = Some(handler.clone());
69            } else {
70                drop(guard);
71                sender.invoke_completed(handler, status);
72            }
73
74            Ok(())
75        }
76    }
77
78    fn spawn<F>(&self, sender: &T, f: F)
79    where
80        F: FnOnce() -> Result<T::Output> + Send + 'static,
81    {
82        let result = f();
83        let mut guard = self.0.lock().unwrap();
84        debug_assert!(guard.result.is_none());
85        guard.result = Some(result);
86        let status = guard.status();
87        let completed = guard.completed.take();
88
89        drop(guard);
90
91        if let Some(completed) = completed {
92            sender.invoke_completed(&completed, status);
93        }
94    }
95}
96
97unsafe impl<T: Async> Send for SyncState<T> {}
98
99#[implement(IAsyncAction, IAsyncInfo)]
100struct Action(SyncState<IAsyncAction>);
101
102#[implement(IAsyncOperation<T>, IAsyncInfo)]
103struct Operation<T>(SyncState<IAsyncOperation<T>>)
104where
105    T: RuntimeType + 'static;
106
107#[implement(IAsyncActionWithProgress<P>, IAsyncInfo)]
108struct ActionWithProgress<P>(SyncState<IAsyncActionWithProgress<P>>)
109where
110    P: RuntimeType + 'static;
111
112#[implement(IAsyncOperationWithProgress<T, P>, IAsyncInfo)]
113struct OperationWithProgress<T, P>(SyncState<IAsyncOperationWithProgress<T, P>>)
114where
115    T: RuntimeType + 'static,
116    P: RuntimeType + 'static;
117
118impl IAsyncInfo_Impl for Action_Impl {
119    fn Id(&self) -> Result<u32> {
120        Ok(1)
121    }
122    fn Status(&self) -> Result<AsyncStatus> {
123        Ok(self.0.status())
124    }
125    fn ErrorCode(&self) -> Result<HRESULT> {
126        Ok(self.0.error_code())
127    }
128    fn Cancel(&self) -> Result<()> {
129        Ok(())
130    }
131    fn Close(&self) -> Result<()> {
132        Ok(())
133    }
134}
135
136impl<T: RuntimeType> IAsyncInfo_Impl for Operation_Impl<T> {
137    fn Id(&self) -> Result<u32> {
138        Ok(1)
139    }
140    fn Status(&self) -> Result<AsyncStatus> {
141        Ok(self.0.status())
142    }
143    fn ErrorCode(&self) -> Result<HRESULT> {
144        Ok(self.0.error_code())
145    }
146    fn Cancel(&self) -> Result<()> {
147        Ok(())
148    }
149    fn Close(&self) -> Result<()> {
150        Ok(())
151    }
152}
153
154impl<P: RuntimeType> IAsyncInfo_Impl for ActionWithProgress_Impl<P> {
155    fn Id(&self) -> Result<u32> {
156        Ok(1)
157    }
158    fn Status(&self) -> Result<AsyncStatus> {
159        Ok(self.0.status())
160    }
161    fn ErrorCode(&self) -> Result<HRESULT> {
162        Ok(self.0.error_code())
163    }
164    fn Cancel(&self) -> Result<()> {
165        Ok(())
166    }
167    fn Close(&self) -> Result<()> {
168        Ok(())
169    }
170}
171
172impl<T: RuntimeType, P: RuntimeType> IAsyncInfo_Impl for OperationWithProgress_Impl<T, P> {
173    fn Id(&self) -> Result<u32> {
174        Ok(1)
175    }
176    fn Status(&self) -> Result<AsyncStatus> {
177        Ok(self.0.status())
178    }
179    fn ErrorCode(&self) -> Result<HRESULT> {
180        Ok(self.0.error_code())
181    }
182    fn Cancel(&self) -> Result<()> {
183        Ok(())
184    }
185    fn Close(&self) -> Result<()> {
186        Ok(())
187    }
188}
189
190impl IAsyncAction_Impl for Action_Impl {
191    fn SetCompleted(&self, handler: Ref<'_, AsyncActionCompletedHandler>) -> Result<()> {
192        self.0.set_completed(&self.as_interface(), handler)
193    }
194    fn Completed(&self) -> Result<AsyncActionCompletedHandler> {
195        Err(Error::empty())
196    }
197    fn GetResults(&self) -> Result<()> {
198        self.0.get_results()
199    }
200}
201
202impl<T: RuntimeType> IAsyncOperation_Impl<T> for Operation_Impl<T> {
203    fn SetCompleted(&self, handler: Ref<'_, AsyncOperationCompletedHandler<T>>) -> Result<()> {
204        self.0.set_completed(&self.as_interface(), handler)
205    }
206    fn Completed(&self) -> Result<AsyncOperationCompletedHandler<T>> {
207        Err(Error::empty())
208    }
209    fn GetResults(&self) -> Result<T> {
210        self.0.get_results()
211    }
212}
213
214impl<P: RuntimeType> IAsyncActionWithProgress_Impl<P> for ActionWithProgress_Impl<P> {
215    fn SetCompleted(
216        &self,
217        handler: Ref<'_, AsyncActionWithProgressCompletedHandler<P>>,
218    ) -> Result<()> {
219        self.0.set_completed(&self.as_interface(), handler)
220    }
221    fn Completed(&self) -> Result<AsyncActionWithProgressCompletedHandler<P>> {
222        Err(Error::empty())
223    }
224    fn GetResults(&self) -> Result<()> {
225        self.0.get_results()
226    }
227    fn SetProgress(&self, _: Ref<'_, AsyncActionProgressHandler<P>>) -> Result<()> {
228        Ok(())
229    }
230    fn Progress(&self) -> Result<AsyncActionProgressHandler<P>> {
231        Err(Error::empty())
232    }
233}
234
235impl<T: RuntimeType, P: RuntimeType> IAsyncOperationWithProgress_Impl<T, P>
236    for OperationWithProgress_Impl<T, P>
237{
238    fn SetCompleted(
239        &self,
240        handler: Ref<'_, AsyncOperationWithProgressCompletedHandler<T, P>>,
241    ) -> Result<()> {
242        self.0.set_completed(&self.as_interface(), handler)
243    }
244    fn Completed(&self) -> Result<AsyncOperationWithProgressCompletedHandler<T, P>> {
245        Err(Error::empty())
246    }
247    fn GetResults(&self) -> Result<T> {
248        self.0.get_results()
249    }
250    fn SetProgress(&self, _: Ref<'_, AsyncOperationProgressHandler<T, P>>) -> Result<()> {
251        Ok(())
252    }
253    fn Progress(&self) -> Result<AsyncOperationProgressHandler<T, P>> {
254        Err(Error::empty())
255    }
256}
257
258impl IAsyncAction {
259    /// Creates an `IAsyncAction` that waits for the closure to execute on the Windows thread pool.
260    pub fn spawn<F>(f: F) -> Self
261    where
262        F: FnOnce() -> Result<()> + Send + 'static,
263    {
264        let object = ComObject::new(Action(SyncState::new()));
265        let interface = object.to_interface();
266
267        windows_threading::submit(move || {
268            object.0.spawn(&object.as_interface(), f);
269        });
270
271        interface
272    }
273}
274
275impl<T: RuntimeType> IAsyncOperation<T> {
276    /// Creates an `IAsyncOperation<T>` that waits for the closure to execute on the Windows thread pool.
277    pub fn spawn<F>(f: F) -> Self
278    where
279        F: FnOnce() -> Result<T> + Send + 'static,
280    {
281        let object = ComObject::new(Operation(SyncState::new()));
282        let interface = object.to_interface();
283
284        windows_threading::submit(move || {
285            object.0.spawn(&object.as_interface(), f);
286        });
287
288        interface
289    }
290}
291
292impl<P: RuntimeType> IAsyncActionWithProgress<P> {
293    /// Creates an `IAsyncActionWithProgress<P>` that waits for the closure to execute on the Windows thread pool.
294    pub fn spawn<F>(f: F) -> Self
295    where
296        F: FnOnce() -> Result<()> + Send + 'static,
297    {
298        let object = ComObject::new(ActionWithProgress(SyncState::new()));
299        let interface = object.to_interface();
300
301        windows_threading::submit(move || {
302            object.0.spawn(&object.as_interface(), f);
303        });
304
305        interface
306    }
307}
308
309impl<T: RuntimeType, P: RuntimeType> IAsyncOperationWithProgress<T, P> {
310    /// Creates an `IAsyncOperationWithProgress<T, P>` that waits for the closure to execute on the Windows thread pool.
311    pub fn spawn<F>(f: F) -> Self
312    where
313        F: FnOnce() -> Result<T> + Send + 'static,
314    {
315        let object = ComObject::new(OperationWithProgress(SyncState::new()));
316        let interface = object.to_interface();
317
318        windows_threading::submit(move || {
319            object.0.spawn(&object.as_interface(), f);
320        });
321
322        interface
323    }
324}