1use std::future::Future;
2use std::pin::Pin;
3use std::sync::Arc;
4use std::task::{Context, Poll};
5
6use atomic_waker::AtomicWaker;
7use crossbeam_channel::{Receiver, Sender};
8
9pub(crate) fn make<T>() -> (Yield<T>, Resume<T>) {
10 let (arg_send, arg_recv) = crossbeam_channel::bounded(1);
11 let waker = Arc::default();
12
13 let future = Yield {
14 waker: Arc::clone(&waker),
15 arg_recv,
16 };
17
18 let resume = Resume { waker, arg_send };
19
20 (future, resume)
21}
22
23pub struct Yield<T> {
26 waker: Arc<AtomicWaker>,
27 arg_recv: Receiver<T>,
28}
29
30impl<T: Send> Future for Yield<T> {
31 type Output = T;
32 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
33 match self.arg_recv.try_recv() {
34 Ok(arg) => Poll::Ready(arg),
35 Err(_) => {
36 self.waker.register(cx.waker());
37 Poll::Pending
38 }
39 }
40 }
41}
42
43pub(crate) struct Resume<T> {
44 waker: Arc<AtomicWaker>,
45 arg_send: Sender<T>,
46}
47
48impl<T: Send> Resume<T> {
49 pub fn resume(self, arg: T) {
51 self.arg_send
52 .send(arg)
53 .expect("sender should not become disconnected");
54
55 self.waker.wake();
56 }
57}