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(&self, handler: Ref<AsyncActionWithProgressCompletedHandler<P>>) -> Result<()> {
216        self.0.set_completed(&self.as_interface(), handler)
217    }
218    fn Completed(&self) -> Result<AsyncActionWithProgressCompletedHandler<P>> {
219        Err(Error::empty())
220    }
221    fn GetResults(&self) -> Result<()> {
222        self.0.get_results()
223    }
224    fn SetProgress(&self, _: Ref<AsyncActionProgressHandler<P>>) -> Result<()> {
225        Ok(())
226    }
227    fn Progress(&self) -> Result<AsyncActionProgressHandler<P>> {
228        Err(Error::empty())
229    }
230}
231
232impl<T: RuntimeType, P: RuntimeType> IAsyncOperationWithProgress_Impl<T, P>
233    for OperationWithProgress_Impl<T, P>
234{
235    fn SetCompleted(
236        &self,
237        handler: Ref<AsyncOperationWithProgressCompletedHandler<T, P>>,
238    ) -> Result<()> {
239        self.0.set_completed(&self.as_interface(), handler)
240    }
241    fn Completed(&self) -> Result<AsyncOperationWithProgressCompletedHandler<T, P>> {
242        Err(Error::empty())
243    }
244    fn GetResults(&self) -> Result<T> {
245        self.0.get_results()
246    }
247    fn SetProgress(&self, _: Ref<AsyncOperationProgressHandler<T, P>>) -> Result<()> {
248        Ok(())
249    }
250    fn Progress(&self) -> Result<AsyncOperationProgressHandler<T, P>> {
251        Err(Error::empty())
252    }
253}
254
255impl IAsyncAction {
256    /// Creates an `IAsyncAction` that waits for the closure to execute on the Windows thread pool.
257    pub fn spawn<F>(f: F) -> Self
258    where
259        F: FnOnce() -> Result<()> + Send + 'static,
260    {
261        let object = ComObject::new(Action(SyncState::new()));
262        let interface = object.to_interface();
263
264        windows_threading::submit(move || {
265            object.0.spawn(&object.as_interface(), f);
266        });
267
268        interface
269    }
270}
271
272impl<T: RuntimeType> IAsyncOperation<T> {
273    /// Creates an `IAsyncOperation<T>` that waits for the closure to execute on the Windows thread pool.
274    pub fn spawn<F>(f: F) -> Self
275    where
276        F: FnOnce() -> Result<T> + Send + 'static,
277    {
278        let object = ComObject::new(Operation(SyncState::new()));
279        let interface = object.to_interface();
280
281        windows_threading::submit(move || {
282            object.0.spawn(&object.as_interface(), f);
283        });
284
285        interface
286    }
287}
288
289impl<P: RuntimeType> IAsyncActionWithProgress<P> {
290    /// Creates an `IAsyncActionWithProgress<P>` that waits for the closure to execute on the Windows thread pool.
291    pub fn spawn<F>(f: F) -> Self
292    where
293        F: FnOnce() -> Result<()> + Send + 'static,
294    {
295        let object = ComObject::new(ActionWithProgress(SyncState::new()));
296        let interface = object.to_interface();
297
298        windows_threading::submit(move || {
299            object.0.spawn(&object.as_interface(), f);
300        });
301
302        interface
303    }
304}
305
306impl<T: RuntimeType, P: RuntimeType> IAsyncOperationWithProgress<T, P> {
307    /// Creates an `IAsyncOperationWithProgress<T, P>` that waits for the closure to execute on the Windows thread pool.
308    pub fn spawn<F>(f: F) -> Self
309    where
310        F: FnOnce() -> Result<T> + Send + 'static,
311    {
312        let object = ComObject::new(OperationWithProgress(SyncState::new()));
313        let interface = object.to_interface();
314
315        windows_threading::submit(move || {
316            object.0.spawn(&object.as_interface(), f);
317        });
318
319        interface
320    }
321}