task_yield/
lib.rs

1//! Executor-independent task yielding
2
3use std::{future::Future, pin::Pin, task::Poll};
4
5/// Yields execution to the `async` executor
6pub fn yield_now() -> Yield {
7    Yield(true)
8}
9
10pub struct Yield(bool);
11
12impl Future for Yield {
13    type Output = ();
14
15    fn poll(mut self: Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> Poll<Self::Output> {
16        if self.0 {
17            cx.waker().wake_by_ref();
18            self.as_mut().0 = false;
19            Poll::Pending
20        } else {
21            Poll::Ready(())
22        }
23    }
24}
25#[cfg(test)]
26mod tests {
27    use super::*;
28
29    #[tokio::test]
30    async fn tokio_test() {
31        use std::cell::Cell;
32        let x = Cell::new(0u32);
33        let a = async {
34            for _ in 0..10000 {
35                x.set(x.get() + 1);
36                yield_now().await;
37            }
38        };
39        let b = async {
40            for i in 0..10000 {
41                assert_eq!(x.get(), i + 1);
42                tokio::task::yield_now().await;
43            }
44        };
45
46        futures::future::join(a, b).await;
47    }
48
49    #[async_std::test]
50    async fn async_std_test() {
51        use std::cell::Cell;
52        let x = Cell::new(0u32);
53        let a = async {
54            for _ in 0..10000 {
55                x.set(x.get() + 1);
56                yield_now().await;
57            }
58        };
59        let b = async {
60            for i in 0..10000 {
61                assert_eq!(x.get(), i + 1);
62                async_std::task::yield_now().await;
63            }
64        };
65
66        futures::future::join(a, b).await;
67    }
68}