Skip to main content

ps_promise/methods/
poll_sync.rs

1use std::task::{Context, Waker};
2
3use crate::{Promise, PromiseRejection};
4
5impl<T, E> Promise<T, E>
6where
7    T: Unpin,
8    E: PromiseRejection,
9{
10    /// Attempts to advance this [`Promise`] immediately on the current thread.
11    ///
12    /// This performs exactly one poll of the underlying future using a no-op waker.
13    ///
14    /// Wakes triggered during this synchronous poll are ignored.
15    /// Execution will effectively resume only when the [`Promise`] is polled again by a real executor.
16    pub fn poll_sync(&mut self) {
17        let waker = Waker::noop();
18        let mut cx = Context::from_waker(waker);
19
20        self.poll(&mut cx);
21    }
22}
23
24#[cfg(test)]
25mod tests {
26    use std::{
27        future::Future,
28        pin::Pin,
29        task::{Context, Poll},
30    };
31
32    use crate::Promise;
33
34    #[test]
35    fn eager_resolves_immediately_ready_future() {
36        let mut promise = Promise::new(async { Ok::<_, ()>(42) });
37        promise.poll_sync();
38
39        match promise {
40            Promise::Resolved(v) => assert_eq!(v, 42),
41            _ => panic!("expected Resolved"),
42        }
43    }
44
45    #[test]
46    fn eager_rejects_immediately_ready_future() {
47        let mut promise: Promise<(), ()> = Promise::new(async { Err(()) });
48        promise.poll_sync();
49
50        match promise {
51            Promise::Rejected(()) => {}
52            _ => panic!("expected Rejected"),
53        }
54    }
55
56    #[test]
57    fn eager_stops_on_pending_without_wake() {
58        struct Never;
59
60        impl Future for Never {
61            type Output = Result<(), ()>;
62
63            fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Self::Output> {
64                Poll::Pending
65            }
66        }
67
68        let mut promise = Promise::new(Never);
69        promise.poll_sync();
70
71        assert!(promise.is_pending());
72    }
73
74    #[test]
75    fn eager_handles_waker_cloning() {
76        struct CloneWaker {
77            stored: Option<std::task::Waker>,
78        }
79
80        impl Future for CloneWaker {
81            type Output = Result<(), ()>;
82
83            fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
84                if self.stored.is_none() {
85                    self.stored = Some(cx.waker().clone());
86                }
87
88                Poll::Pending
89            }
90        }
91
92        let mut promise = Promise::new(CloneWaker { stored: None });
93        promise.poll_sync();
94
95        assert!(promise.is_pending());
96    }
97}