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}