libasync_dispatcher/
task.rs1use core::task::Context;
8use fuchsia_sync::Mutex;
9use std::pin::Pin;
10use std::sync::atomic::{AtomicBool, Ordering};
11use std::sync::{Arc, mpsc};
12use std::task::{Poll, Wake, Waker};
13
14use zx_status::Status;
15
16use futures::future::{BoxFuture, FutureExt};
17use futures::task::AtomicWaker;
18
19use crate::{AsAsyncDispatcherRef, AsyncDispatcher};
20
21#[must_use]
24#[derive(Debug)]
25pub struct Task<T> {
26 state: Arc<TaskFutureState>,
27 result_receiver: mpsc::Receiver<Result<T, Status>>,
28 detached: bool,
29}
30
31impl<T: Send + 'static> Task<T> {
32 fn new(
33 future: impl Future<Output = T> + Send + 'static,
34 dispatcher: AsyncDispatcher,
35 ) -> (Self, Arc<TaskWakerState<T>>) {
36 let future_state = Arc::new(TaskFutureState {
37 waker: AtomicWaker::new(),
38 aborted: AtomicBool::new(false),
39 });
40 let (result_sender, result_receiver) = mpsc::sync_channel(1);
41 let state = Arc::new(TaskWakerState {
42 result_sender,
43 future_state: future_state.clone(),
44 future: Mutex::new(Some(future.boxed())),
45 dispatcher,
46 });
47 let future = Task { state: future_state, result_receiver, detached: false };
48 (future, state)
49 }
50
51 pub fn new_failed(status: Status) -> Self {
53 let state = Arc::new(TaskFutureState {
54 waker: AtomicWaker::new(),
55 aborted: AtomicBool::new(false),
56 });
57 let (result_sender, result_receiver) = mpsc::sync_channel(1);
58 result_sender.try_send(Err(status)).unwrap();
61 Task { state, result_receiver, detached: false }
62 }
63
64 pub(crate) fn start(
65 future: impl Future<Output = T> + Send + 'static,
66 dispatcher: AsyncDispatcher,
67 ) -> Self {
68 let (future, state) = Self::new(future, dispatcher);
69
70 if let Err(err) = state.queue() {
73 drop(state.future.lock().take());
75 state.result_sender.try_send(Err(err)).unwrap();
78 }
79
80 future
81 }
82}
83
84impl<T> Task<T> {
85 pub fn detach(self) {
89 drop(self.detach_on_drop());
90 }
91
92 pub fn detach_on_drop(mut self) -> JoinHandle<T> {
98 self.detached = true;
99 JoinHandle(self)
100 }
101
102 pub fn abort(&self) {
106 self.state.aborted.store(true, Ordering::Relaxed);
107 }
108}
109
110impl<T> Drop for Task<T> {
111 fn drop(&mut self) {
112 if !self.detached {
113 self.state.aborted.store(true, Ordering::Relaxed);
114 }
115 }
116}
117
118#[derive(Debug)]
119struct TaskFutureState {
120 waker: AtomicWaker,
121 aborted: AtomicBool,
122}
123
124impl<T> Future for Task<T> {
125 type Output = Result<T, Status>;
126
127 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
128 use std::sync::mpsc::TryRecvError;
129 self.state.waker.register(cx.waker());
130 match self.result_receiver.try_recv() {
131 Ok(res) => Poll::Ready(res),
132 Err(TryRecvError::Disconnected) => Poll::Ready(Err(Status::CANCELED)),
133 Err(TryRecvError::Empty) => Poll::Pending,
134 }
135 }
136}
137
138#[derive(Debug)]
140pub struct JoinHandle<T>(Task<T>);
141
142impl<T> JoinHandle<T> {
143 pub fn abort(&self) {
147 self.0.abort()
148 }
149}
150
151impl<T> Future for JoinHandle<T> {
152 type Output = Result<T, Status>;
153
154 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
155 self.0.poll_unpin(cx)
156 }
157}
158
159struct TaskWakerState<T> {
160 result_sender: mpsc::SyncSender<Result<T, Status>>,
161 future_state: Arc<TaskFutureState>,
162 future: Mutex<Option<BoxFuture<'static, T>>>,
163 dispatcher: AsyncDispatcher,
164}
165
166impl<T: Send + 'static> Wake for TaskWakerState<T> {
167 fn wake(self: Arc<Self>) {
168 self.wake_by_ref();
169 }
170 fn wake_by_ref(self: &Arc<Self>) {
171 match self.queue() {
172 Err(e) if e == Status::BAD_STATE => {
173 let future_slot = self.future.lock().take();
176 drop(future_slot);
177 self.send_result(Err(e));
178 }
179 res => res.expect("Unexpected error waking dispatcher task"),
180 }
181 }
182}
183
184impl<T: Send + 'static> TaskWakerState<T> {
185 fn send_result(&self, res: Result<T, Status>) {
187 self.result_sender.try_send(res).ok();
191 self.future_state.waker.wake();
192 }
193
194 pub(crate) fn queue(self: &Arc<Self>) -> Result<(), Status> {
198 let arc_self = self.clone();
199 self.dispatcher
200 .post_task_sync(move |status| {
201 let mut future_slot = arc_self.future.lock();
202 if let Err(status) = status {
205 drop(future_slot.take());
206 arc_self.send_result(Err(status));
207 return;
208 }
209
210 if arc_self.future_state.aborted.load(Ordering::Relaxed) {
213 drop(future_slot.take());
214 arc_self.send_result(Err(Status::CANCELED));
215 return;
216 }
217
218 let Some(mut future) = future_slot.take() else {
219 return;
220 };
221 let waker = Waker::from(arc_self.clone());
222 let context = &mut Context::from_waker(&waker);
223 match future.as_mut().poll(context) {
224 Poll::Pending => *future_slot = Some(future),
225 Poll::Ready(res) => {
226 arc_self.send_result(Ok(res));
227 }
228 }
229 })
230 .map(|_| ())
231 }
232}