1#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
4#![warn(missing_docs)]
5
6use std::{
7 cell::RefCell,
8 future::Future,
9 hint::unreachable_unchecked,
10 pin::Pin,
11 task::{Context, Poll, Waker},
12};
13
14pub trait Runnable {
16 fn run();
19}
20
21impl Runnable for () {
22 fn run() {}
23}
24
25#[derive(Debug)]
26enum WakerState<T> {
27 Inactive,
28 Active(Waker),
29 Signaled(T),
30}
31
32#[derive(Debug)]
34pub struct Callback<T = ()>(RefCell<WakerState<T>>);
35
36impl<T> Default for Callback<T> {
37 fn default() -> Self {
38 Self::new()
39 }
40}
41
42impl<T> Callback<T> {
43 pub fn new() -> Self {
45 Self(RefCell::new(WakerState::Inactive))
46 }
47
48 pub fn signal<R: Runnable>(&self, v: T) -> bool {
51 let mut state = self.0.borrow_mut();
52 match &*state {
53 WakerState::Inactive => return true,
54 WakerState::Signaled(_) => {
55 }
58 WakerState::Active(waker) => {
59 waker.wake_by_ref();
60 }
61 }
62 *state = WakerState::Signaled(v);
63 drop(state);
64 R::run();
65 false
66 }
67
68 pub(crate) fn register(&self, waker: &Waker) -> Poll<T> {
69 let mut state = self.0.borrow_mut();
70 match &*state {
71 WakerState::Signaled(_) => {
72 let state = std::mem::replace(&mut *state, WakerState::Inactive);
73 let v = if let WakerState::Signaled(v) = state {
74 v
75 } else {
76 unsafe { unreachable_unchecked() }
78 };
79 Poll::Ready(v)
80 }
81 _ => {
82 *state = WakerState::Active(waker.clone());
83 Poll::Pending
84 }
85 }
86 }
87
88 pub fn wait(&self) -> impl Future<Output = T> + '_ {
90 WaitFut(self)
91 }
92}
93
94struct WaitFut<'a, T>(&'a Callback<T>);
95
96impl<T> Future for WaitFut<'_, T> {
97 type Output = T;
98
99 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
100 self.0.register(cx.waker())
101 }
102}
103
104impl<T> Drop for WaitFut<'_, T> {
105 fn drop(&mut self) {
106 *self.0.0.borrow_mut() = WakerState::Inactive;
108 }
109}