Skip to main content

qubit_executor/executor/
delay_executor.rs

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