Skip to main content

qubit_executor/executor/
delay_executor.rs

1/*******************************************************************************
2 *
3 *    Copyright (c) 2025 - 2026.
4 *    Haixing Hu, Qubit Co. Ltd.
5 *
6 *    All rights reserved.
7 *
8 ******************************************************************************/
9use std::{
10    thread,
11    time::Duration,
12};
13
14use qubit_function::Callable;
15
16use crate::{
17    TaskCompletionPair,
18    TaskHandle,
19    TaskRunner,
20};
21
22use super::Executor;
23
24/// Executor that starts each task after a fixed delay.
25///
26/// `DelayExecutor` models delayed start, not minimum execution duration. The
27/// returned [`TaskHandle`] is created immediately. A helper thread sleeps for
28/// the configured delay and then runs the task. Dropping the handle does not
29/// cancel the helper thread.
30///
31/// # Author
32///
33/// Haixing Hu
34#[derive(Debug, Clone, Copy, PartialEq, Eq)]
35pub struct DelayExecutor {
36    /// Duration to sleep before each submitted task starts.
37    delay: Duration,
38}
39
40impl DelayExecutor {
41    /// Creates an executor that delays task start by the supplied duration.
42    ///
43    /// # Parameters
44    ///
45    /// * `delay` - Duration to wait before running each task.
46    ///
47    /// # Returns
48    ///
49    /// A delay executor using the supplied delay.
50    #[inline]
51    pub const fn new(delay: Duration) -> Self {
52        Self { delay }
53    }
54
55    /// Returns the configured delay.
56    ///
57    /// # Returns
58    ///
59    /// The duration waited before each task starts.
60    #[inline]
61    pub const fn delay(&self) -> Duration {
62        self.delay
63    }
64}
65
66impl Executor for DelayExecutor {
67    type Execution<R, E>
68        = TaskHandle<R, E>
69    where
70        R: Send + 'static,
71        E: std::fmt::Display + Send + 'static;
72
73    /// Starts a helper thread that waits and then runs the callable.
74    ///
75    /// # Parameters
76    ///
77    /// * `task` - Callable to run after the configured delay.
78    ///
79    /// # Returns
80    ///
81    /// A [`TaskHandle`] for the delayed task.
82    fn call<C, R, E>(&self, task: C) -> Self::Execution<R, E>
83    where
84        C: Callable<R, E> + Send + 'static,
85        R: Send + 'static,
86        E: std::fmt::Display + Send + 'static,
87    {
88        let (handle, completion) = TaskCompletionPair::new().into_parts();
89        let delay = self.delay;
90        thread::spawn(move || {
91            if !delay.is_zero() {
92                thread::sleep(delay);
93            }
94            TaskRunner::new(task).run(completion);
95        });
96        handle
97    }
98}