qubit_executor/task/task_handle.rs
1/*******************************************************************************
2 *
3 * Copyright (c) 2025 - 2026.
4 * Haixing Hu, Qubit Co. Ltd.
5 *
6 * All rights reserved.
7 *
8 ******************************************************************************/
9use std::{
10 future::Future,
11 pin::Pin,
12 sync::Arc,
13 task::{
14 Context,
15 Poll,
16 },
17};
18
19use super::TaskResult;
20use super::task_completion::TaskCompletion;
21use super::task_handle_inner::TaskHandleInner;
22
23/// Handle for a task running outside the caller's current stack.
24///
25/// `TaskHandle` is returned by thread-backed executors and services. Calling
26/// [`Self::get`] blocks the current thread until the accepted task completes.
27/// Awaiting the handle waits asynchronously for the same final task result.
28///
29/// # Type Parameters
30///
31/// * `R` - The task success value.
32/// * `E` - The task error value.
33///
34/// # Author
35///
36/// Haixing Hu
37pub struct TaskHandle<R, E> {
38 /// Shared state observed by the handle and updated by completion endpoints.
39 pub(crate) inner: Arc<TaskHandleInner<R, E>>,
40}
41
42impl<R, E> TaskHandle<R, E> {
43 /// Waits for the task to finish and returns its final result.
44 ///
45 /// This method blocks the current thread until a result is available.
46 ///
47 /// # Returns
48 ///
49 /// `Ok(R)` if the task succeeds. If the accepted task returns `Err(E)`,
50 /// panics, or is cancelled before producing a value, the corresponding
51 /// [`crate::TaskExecutionError`] is returned.
52 pub fn get(self) -> TaskResult<R, E> {
53 self.inner.state.wait_until(
54 |state| state.completed,
55 |state| {
56 state
57 .result
58 .take()
59 .expect("task handle completed without a result")
60 },
61 )
62 }
63
64 /// Returns whether the task has reported completion.
65 ///
66 /// # Returns
67 ///
68 /// `true` after the task runner has produced or abandoned its final result.
69 #[inline]
70 pub fn is_done(&self) -> bool {
71 self.inner.done.load()
72 }
73
74 /// Attempts to cancel the task.
75 ///
76 /// Cancellation can only win before the runner marks the task as started.
77 /// It cannot interrupt a task that is already running on an OS thread.
78 ///
79 /// # Returns
80 ///
81 /// `true` if the task was cancelled before it started, or `false` if the
82 /// task was already running or completed.
83 #[inline]
84 pub fn cancel(&self) -> bool {
85 TaskCompletion {
86 inner: Arc::clone(&self.inner),
87 }
88 .cancel()
89 }
90}
91
92impl<R, E> Future for TaskHandle<R, E> {
93 type Output = TaskResult<R, E>;
94
95 /// Polls this handle for the accepted task's final result.
96 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
97 let result = self.inner.state.write(|state| {
98 if state.completed {
99 Some(
100 state
101 .result
102 .take()
103 .expect("task handle completed without a result"),
104 )
105 } else {
106 state.waker = Some(cx.waker().clone());
107 None
108 }
109 });
110 if let Some(result) = result {
111 Poll::Ready(result)
112 } else {
113 Poll::Pending
114 }
115 }
116}