1use std::sync::{Arc, Condvar, Mutex};
8
9use mssf_com::FabricCommon::{
10 IFabricAsyncOperationCallback, IFabricAsyncOperationCallback_Impl,
11 IFabricAsyncOperationContext, IFabricAsyncOperationContext_Impl,
12};
13use windows_core::implement;
14
15#[derive(Debug)]
16#[implement(IFabricAsyncOperationCallback)]
17pub struct WaitableCallback {
18 pair_: Arc<(Mutex<bool>, Condvar)>,
19}
20
21pub struct WaitableToken {
22 pair_: Arc<(Mutex<bool>, Condvar)>,
23}
24
25impl Default for WaitableCallback {
26 fn default() -> Self {
27 Self::new()
28 }
29}
30
31impl WaitableCallback {
32 pub fn channel() -> (WaitableToken, IFabricAsyncOperationCallback) {
33 let callback = WaitableCallback::new();
34 let token = WaitableToken {
35 pair_: callback.pair_.clone(),
36 };
37 let i_callbaack = callback.into();
38 (token, i_callbaack)
39 }
40
41 pub fn new() -> WaitableCallback {
42 WaitableCallback {
43 pair_: Arc::new((Mutex::new(false), Condvar::new())),
44 }
45 }
46}
47
48impl IFabricAsyncOperationCallback_Impl for WaitableCallback_Impl {
49 fn Invoke(&self, _context: windows_core::Ref<IFabricAsyncOperationContext>) {
51 let (lock, cvar) = &*self.pair_;
53 let mut started = lock.lock().unwrap();
54 *started = true;
55 cvar.notify_one();
57 }
58}
59
60impl WaitableToken {
61 pub fn wait(&self) {
62 let (lock, cvar) = &*self.pair_;
65 let mut started = lock.lock().unwrap();
66 while !*started {
67 started = cvar.wait(started).unwrap();
68 }
69 }
70}
71
72#[derive(Debug)]
75#[implement(IFabricAsyncOperationContext)]
76pub struct AsyncContext {
77 callback_: IFabricAsyncOperationCallback,
78}
79
80impl AsyncContext {
81 pub fn new(callback: core::option::Option<&IFabricAsyncOperationCallback>) -> AsyncContext {
84 let callback_copy: IFabricAsyncOperationCallback = callback.expect("msg").clone();
85
86 AsyncContext {
87 callback_: callback_copy,
88 }
89 }
90}
91
92impl IFabricAsyncOperationContext_Impl for AsyncContext_Impl {
93 fn IsCompleted(&self) -> bool {
94 true
95 }
96
97 fn CompletedSynchronously(&self) -> bool {
98 true
99 }
100
101 fn Callback(&self) -> crate::WinResult<IFabricAsyncOperationCallback> {
102 let callback_copy: IFabricAsyncOperationCallback = self.callback_.clone();
104 Ok(callback_copy)
105 }
106
107 fn Cancel(&self) -> crate::WinResult<()> {
108 Ok(())
109 }
110}
111
112#[cfg(test)]
113mod tests {
114 use mssf_com::FabricCommon::IFabricAsyncOperationContext;
115
116 use super::{AsyncContext, WaitableCallback};
117
118 #[test]
119 fn test_waitable_callback() {
120 let (token, callback) = WaitableCallback::channel();
121 let ctx: IFabricAsyncOperationContext = AsyncContext::new(Some(&callback)).into();
122 unsafe { ctx.Callback().unwrap().Invoke(&ctx) };
123 token.wait();
124 }
125}