native_executor/
timer.rs

1//! Platform-native timers with high precision.
2//!
3//! Leverages OS scheduling primitives (GCD `dispatch_after` on Apple) for accurate
4//! timing without busy-waiting.
5//!
6//! ```rust
7//! use native_executor::timer::{Timer, sleep};
8//! use std::time::Duration;
9//!
10//! # async {
11//! Timer::after(Duration::from_millis(100)).await;  // Precise timing
12//! Timer::after_secs(2).await;                      // Convenience method  
13//! sleep(1).await;                                  // Simple sleep
14//! # };
15//! ```
16
17use core::{
18    future::Future,
19    pin::Pin,
20    sync::atomic::{AtomicBool, Ordering},
21    task::{Context, Poll},
22    time::Duration,
23};
24
25use alloc::sync::Arc;
26
27use crate::{NativeExecutor, PlatformExecutor};
28
29/// A high-precision future that completes after a specified duration.
30///
31/// `Timer` provides platform-native timing capabilities that leverage operating system
32/// scheduling primitives for accurate delays without busy-waiting. The timer integrates
33/// seamlessly with async/await and provides zero-cost abstraction over native OS APIs.
34///
35/// # Platform Behavior
36/// - **Apple platforms**: Uses GCD's `dispatch_after` for precise scheduling
37/// - **Other platforms**: Will use platform-specific high-resolution APIs
38///
39/// # Performance
40/// Unlike thread-based sleep implementations, `Timer` doesn't block threads and
41/// allows the executor to handle other tasks while waiting.
42///
43/// # Examples
44/// ```rust
45/// use native_executor::timer::Timer;
46/// use std::time::Duration;
47///
48/// async fn precise_timing() {
49///     // Millisecond precision timing
50///     Timer::after(Duration::from_millis(250)).await;
51///     
52///     // Second-based convenience method
53///     Timer::after_secs(2).await;
54/// }
55/// ```
56#[derive(Debug)]
57pub struct Timer {
58    /// The duration to wait. This is taken (set to None) after the timer is started.
59    duration: Option<Duration>,
60    /// Atomic flag to track whether the timer has completed.
61    /// This is shared between the future and the callback that will be executed after the duration.
62    finished: Arc<AtomicBool>,
63}
64
65impl Timer {
66    /// Creates a new `Timer` that will complete after the specified duration.
67    ///
68    /// # Arguments
69    ///
70    /// * `duration` - The amount of time to wait before the timer completes.
71    ///
72    /// # Returns
73    ///
74    /// A new `Timer` instance that can be awaited.
75    ///
76    /// # Example
77    ///
78    /// ```
79    /// use native_executor::timer::Timer;
80    /// use std::time::Duration;
81    ///
82    /// async fn example() {
83    ///     // Wait for 1 second
84    ///     Timer::after(Duration::from_secs(1)).await;
85    ///     println!("One second has passed!");
86    /// }
87    /// ```
88    #[must_use]
89    pub fn after(duration: Duration) -> Self {
90        Self {
91            duration: Some(duration),
92            finished: Arc::default(),
93        }
94    }
95
96    /// Creates a new `Timer` that will complete after the specified number of seconds.
97    ///
98    /// This is a convenience method that wraps `Timer::after` with `Duration::from_secs`.
99    ///
100    /// # Arguments
101    ///
102    /// * `secs` - The number of seconds to wait before the timer completes.
103    ///
104    /// # Returns
105    ///
106    /// A new `Timer` instance that can be awaited.
107    ///
108    /// # Example
109    ///
110    /// ```
111    /// use native_executor::timer::Timer;
112    ///
113    /// async fn example() {
114    ///     // Wait for 5 seconds
115    ///     Timer::after_secs(5).await;
116    ///     println!("Five seconds have passed!");
117    /// }
118    /// ```
119    #[must_use]
120    pub fn after_secs(secs: u64) -> Self {
121        Self::after(Duration::from_secs(secs))
122    }
123}
124
125impl Future for Timer {
126    type Output = ();
127
128    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
129        // If the timer has already finished, return Ready
130        if self.finished.load(Ordering::Acquire) {
131            return Poll::Ready(());
132        }
133
134        // If this is the first poll, set up the timer
135        if let Some(duration) = self.duration.take() {
136            let waker = cx.waker().clone();
137            let finished = self.finished.clone();
138
139            // Schedule the callback to run after the specified duration
140            NativeExecutor::exec_after(duration, move || {
141                // Mark the timer as finished
142                finished.store(true, Ordering::Release);
143                // Wake the task that's waiting on this timer
144                waker.wake();
145            });
146        }
147
148        // The timer hasn't completed yet
149        Poll::Pending
150    }
151}
152
153/// Suspends the current async task for the specified number of seconds.
154///
155/// This convenience function provides a simple interface for second-based delays,
156/// using the same high-precision platform-native timing as `Timer::after`.
157///
158/// # Arguments
159/// * `secs` - The number of seconds to sleep
160///
161/// # Platform Integration
162/// Uses the same platform-native scheduling as `Timer` for consistent precision.
163///
164/// # Examples
165/// ```rust
166/// use native_executor::timer::sleep;
167///
168/// async fn delayed_operation() {
169///     println!("Starting operation");
170///     sleep(2).await;  // High-precision 2-second delay
171///     println!("Operation resumed after 2 seconds");
172/// }
173/// ```
174pub async fn sleep(secs: u64) {
175    Timer::after(Duration::from_secs(secs)).await;
176}