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}