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}