1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 
5 use moz_task;
6 use std::{
7     future::Future,
8     pin::Pin,
9     sync::atomic::{AtomicBool, Ordering::Relaxed},
10     sync::Arc,
11     task::{Context, Poll, Waker},
12 };
13 
14 /// Demo `Future` to demonstrate executing futures to completion via `nsIEventTarget`.
15 struct MyFuture {
16     poll_count: u32,
17     waker: Option<Waker>,
18 }
19 
20 impl Default for MyFuture {
default() -> Self21     fn default() -> Self {
22         Self {
23             poll_count: 0,
24             waker: None,
25         }
26     }
27 }
28 
29 impl Future for MyFuture {
30     type Output = ();
31 
poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()>32     fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
33         self.poll_count += 1;
34 
35         if let Some(waker) = &mut self.waker {
36             if !waker.will_wake(cx.waker()) {
37                 *waker = cx.waker().clone();
38             }
39         } else {
40             let waker = cx.waker().clone();
41             self.waker = Some(waker);
42         }
43 
44         println!("Poll count = {}", self.poll_count);
45         if self.poll_count > 5 {
46                 Poll::Ready(())
47         } else {
48             // Just notify the task that we need to re-polled.
49             if let Some(waker) = &self.waker {
50                 waker.wake_by_ref();
51             }
52             Poll::Pending
53         }
54     }
55 }
56 
57 #[no_mangle]
Rust_Future(it_worked: *mut bool)58 pub extern "C" fn Rust_Future(it_worked: *mut bool) {
59     let done = Arc::new(AtomicBool::new(false));
60     let done2 = done.clone();
61 
62     moz_task::spawn_current_thread(async move {
63         MyFuture::default().await;
64         done.store(true, Relaxed);
65     })
66     .unwrap();
67 
68     unsafe {
69         moz_task::gtest_only::spin_event_loop_until(move || done2.load(Relaxed)).unwrap();
70         *it_worked = true;
71     };
72 }
73