codas_flow/
async_support.rs

1//! Runtime-agnostic `async` utilities.
2
3use core::{
4    future::Future,
5    pin::Pin,
6    ptr::null,
7    task::{Poll, RawWaker, RawWakerVTable, Waker},
8};
9
10/// Returns a future that becomes ready
11/// after one poll, emulating a yield on
12/// most async runtimes.
13pub async fn yield_now() {
14    YieldNow::Pending.await
15}
16
17/// Future returned by [`yield_now`].
18enum YieldNow {
19    /// The future has not yet yielded.
20    Pending,
21
22    /// The future has yielded for
23    /// at least one poll cycle, and
24    /// is now ready.
25    Ready,
26}
27
28impl Future for YieldNow {
29    type Output = ();
30
31    fn poll(mut self: Pin<&mut Self>, cx: &mut core::task::Context<'_>) -> Poll<Self::Output> {
32        match *self {
33            YieldNow::Pending => {
34                *self = YieldNow::Ready;
35                cx.waker().wake_by_ref();
36                Poll::Pending
37            }
38            YieldNow::Ready => Poll::Ready(()),
39        }
40    }
41}
42
43/// Returns an asynchronous [`Waker`] that
44/// does nothing at all.
45///
46/// This implementation is based on the
47/// [`futures` crate](https://github.com/rust-lang/futures-rs),
48/// and may be removed in the future.
49#[inline]
50pub(crate) fn noop_waker() -> Waker {
51    unsafe { Waker::from_raw(noop_raw_waker()) }
52}
53
54const NOOP_WAKER_VTABLE: RawWakerVTable = RawWakerVTable::new(noop_clone, noop, noop, noop);
55
56const unsafe fn noop_clone(_data: *const ()) -> RawWaker {
57    noop_raw_waker()
58}
59
60const unsafe fn noop(_data: *const ()) {}
61
62const fn noop_raw_waker() -> RawWaker {
63    RawWaker::new(null(), &NOOP_WAKER_VTABLE)
64}