1use crate::DecodeError;
3use std::future::Future;
4use std::pin::Pin;
5use std::task::{Context, Poll, Waker};
6
7type Outcome<T> = Result<T, DecodeError>;
8type BoxedFuture<T> = Pin<Box<dyn Future<Output = Outcome<T>>>>;
9
10pub struct Pending<T> {
19 future: Option<BoxedFuture<T>>,
20}
21
22impl<T> Pending<T> {
23 pub(crate) fn inline(job: impl FnOnce() -> Outcome<T> + 'static) -> Self
25 where
26 T: 'static,
27 {
28 Self::from_future(async move { job() })
29 }
30
31 pub(crate) fn from_future(future: impl Future<Output = Outcome<T>> + 'static) -> Self {
32 Self {
33 future: Some(Box::pin(future)),
34 }
35 }
36
37 pub fn try_take(&mut self) -> Option<Outcome<T>> {
45 let mut context = Context::from_waker(Waker::noop());
46 match self.poll_inner(&mut context) {
47 Poll::Ready(result) => Some(result),
48 Poll::Pending => None,
49 }
50 }
51
52 fn poll_inner(&mut self, context: &mut Context<'_>) -> Poll<Outcome<T>> {
53 let future = self
54 .future
55 .as_mut()
56 .expect("Pending polled after it completed");
57 let result = future.as_mut().poll(context);
58 if result.is_ready() {
59 self.future = None;
60 }
61 result
62 }
63}
64
65impl<T> Future for Pending<T> {
66 type Output = Outcome<T>;
67
68 fn poll(self: Pin<&mut Self>, context: &mut Context<'_>) -> Poll<Self::Output> {
69 self.get_mut().poll_inner(context)
70 }
71}
72
73impl<T> std::fmt::Debug for Pending<T> {
74 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
75 f.debug_struct("Pending")
76 .field("completed", &self.future.is_none())
77 .finish()
78 }
79}
80
81#[cfg(all(feature = "worker", not(target_arch = "wasm32")))]
82pub(crate) use shared::{reply, Reply};
83
84#[cfg(all(feature = "worker", not(target_arch = "wasm32")))]
86mod shared {
87 use super::*;
88 use std::sync::{Arc, Mutex};
89
90 enum State<T> {
91 Waiting(Option<Waker>),
92 Ready(Outcome<T>),
93 Taken,
94 Cancelled,
95 }
96
97 struct Slot<T>(Mutex<State<T>>);
98
99 impl<T> Slot<T> {
100 fn lock(&self) -> std::sync::MutexGuard<'_, State<T>> {
101 self.0
102 .lock()
103 .unwrap_or_else(|poisoned| poisoned.into_inner())
104 }
105 }
106
107 pub(crate) fn reply<T>() -> (impl Future<Output = Outcome<T>>, Reply<T>) {
109 let slot = Arc::new(Slot(Mutex::new(State::Waiting(None))));
110 (Awaiting(slot.clone()), Reply(slot))
111 }
112
113 struct Awaiting<T>(Arc<Slot<T>>);
114
115 impl<T> Future for Awaiting<T> {
116 type Output = Outcome<T>;
117
118 fn poll(self: Pin<&mut Self>, context: &mut Context<'_>) -> Poll<Self::Output> {
119 let mut state = self.0.lock();
120 match &mut *state {
121 State::Waiting(waker) => {
122 *waker = Some(context.waker().clone());
123 Poll::Pending
124 }
125 State::Ready(_) => match std::mem::replace(&mut *state, State::Taken) {
126 State::Ready(result) => Poll::Ready(result),
127 _ => unreachable!("matched Ready under the same lock"),
128 },
129 State::Taken => panic!("decode result taken twice"),
130 State::Cancelled => unreachable!("only a dropped future cancels"),
131 }
132 }
133 }
134
135 impl<T> Drop for Awaiting<T> {
137 fn drop(&mut self) {
138 let mut state = self.0.lock();
139 if matches!(*state, State::Waiting(_)) {
140 *state = State::Cancelled;
141 }
142 }
143 }
144
145 pub(crate) struct Reply<T>(Arc<Slot<T>>);
147
148 impl<T> Reply<T> {
149 pub(crate) fn is_cancelled(&self) -> bool {
151 matches!(*self.0.lock(), State::Cancelled)
152 }
153
154 pub(crate) fn send(self, result: Outcome<T>) -> Result<(), Outcome<T>> {
156 deliver(&self.0, result)
157 }
158 }
159
160 impl<T> Drop for Reply<T> {
163 fn drop(&mut self) {
164 let _ = deliver(&self.0, Err(DecodeError::Closed));
165 }
166 }
167
168 fn deliver<T>(slot: &Slot<T>, result: Outcome<T>) -> Result<(), Outcome<T>> {
170 let mut state = slot.lock();
171 let State::Waiting(waker) = &mut *state else {
172 return Err(result);
173 };
174 let waker = waker.take();
175 *state = State::Ready(result);
176 drop(state);
177 if let Some(waker) = waker {
178 waker.wake();
179 }
180 Ok(())
181 }
182}