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