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