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}