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