Skip to main content

qubit_executor/task/
task_runner.rs

1/*******************************************************************************
2 *
3 *    Copyright (c) 2025 - 2026.
4 *    Haixing Hu, Qubit Co. Ltd.
5 *
6 *    All rights reserved.
7 *
8 ******************************************************************************/
9use std::panic::{
10    AssertUnwindSafe,
11    catch_unwind,
12};
13
14use qubit_function::Callable;
15
16use super::{
17    TaskCompletion,
18    TaskExecutionError,
19    TaskResult,
20};
21
22/// Runner that executes a callable task with standard task-handle semantics.
23///
24/// `TaskRunner` owns the accepted callable, converts task failures and panics
25/// into [`TaskExecutionError`], and can publish the final result through a
26/// [`TaskCompletion`] endpoint.
27pub struct TaskRunner<C> {
28    /// Callable task owned by this runner.
29    task: C,
30}
31
32impl<C> TaskRunner<C> {
33    /// Creates a runner for the supplied callable task.
34    ///
35    /// # Parameters
36    ///
37    /// * `task` - Callable task to execute later.
38    ///
39    /// # Returns
40    ///
41    /// A runner that owns the callable task.
42    #[inline]
43    pub const fn new(task: C) -> Self {
44        Self { task }
45    }
46
47    /// Runs the callable and converts task failure and panic into a handle result.
48    ///
49    /// # Returns
50    ///
51    /// `Ok(R)` if the task succeeds. If the task returns `Err(E)` or panics, the
52    /// corresponding [`TaskExecutionError`] is returned.
53    pub fn call<R, E>(self) -> TaskResult<R, E>
54    where
55        C: Callable<R, E>,
56    {
57        let mut task = self.task;
58        match catch_unwind(AssertUnwindSafe(|| task.call())) {
59            Ok(Ok(value)) => Ok(value),
60            Ok(Err(err)) => Err(TaskExecutionError::Failed(err)),
61            Err(_) => Err(TaskExecutionError::Panicked),
62        }
63    }
64
65    /// Runs this task through a task completion endpoint.
66    ///
67    /// # Parameters
68    ///
69    /// * `completion` - Completion endpoint that publishes the final result.
70    ///
71    /// # Returns
72    ///
73    /// `true` if the task started and its result was published, or `false` if
74    /// the completion endpoint had already been completed by cancellation.
75    #[inline]
76    pub fn run<R, E>(self, completion: TaskCompletion<R, E>) -> bool
77    where
78        C: Callable<R, E>,
79    {
80        completion.start_and_complete(|| self.call())
81    }
82}