1use core::cell::UnsafeCell;
7use core::fmt;
8use core::future::Future;
9use core::marker::PhantomData;
10use core::mem::ManuallyDrop;
11use core::pin::Pin;
12use core::task::{Context, Poll, Waker};
13use std::sync::Arc;
14use std::task::Wake;
15use std::time::Duration;
16
17use super::{Instant, clock};
18
19use super::wheel::{TimerKey, Wheel};
20use crate::rt::context;
21use crate::rt::shard::{Shard, Shared};
22use crate::sync::atomic_waker::AtomicWaker;
23use crate::sync::internal::{AtomicBool, Ordering};
24
25#[inline(always)]
32pub fn sleep(duration: Duration) -> Sleep {
33 Sleep {
34 timer: Timer::after(duration),
35 }
36}
37
38pub fn sleep_until(deadline: impl Into<Instant>) -> Sleep {
40 Sleep {
41 timer: Timer::new(deadline.into()),
42 }
43}
44
45pub(super) fn far_future() -> Instant {
47 Instant::now() + Duration::from_secs(86_400 * 365 * 30)
48}
49
50#[must_use = "a sleep does nothing unless awaited"]
58pub struct Sleep {
59 timer: Timer<Coarse>,
60}
61
62impl Sleep {
63 pub fn deadline(&self) -> Instant {
65 self.timer.deadline()
66 }
67
68 pub fn is_elapsed(&self) -> bool {
70 self.timer.is_elapsed()
71 }
72
73 pub fn reset(self: Pin<&mut Self>, deadline: impl Into<Instant>) {
75 self.get_mut().timer.reset(deadline.into());
76 }
77}
78
79impl Future for Sleep {
80 type Output = ();
81
82 #[inline(always)]
83 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
84 self.get_mut().timer.poll(cx)
85 }
86}
87
88impl fmt::Debug for Sleep {
89 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
90 f.debug_struct("Sleep")
91 .field("deadline", &self.deadline())
92 .field("elapsed", &self.is_elapsed())
93 .finish()
94 }
95}
96
97pub(crate) trait Grain {
99 const PRECISE: bool;
101}
102
103pub(crate) struct Coarse;
105
106impl Grain for Coarse {
107 const PRECISE: bool = false;
108}
109
110pub(crate) struct Fine;
112
113impl Grain for Fine {
114 const PRECISE: bool = true;
115}
116
117pub(super) struct Timer<G: Grain> {
120 deadline: Deadline,
121 state: ManuallyDrop<State>,
124 grain: PhantomData<G>,
125}
126
127#[derive(Clone, Copy)]
131enum Deadline {
132 Nanos(u64),
135 Given(Instant),
138}
139
140enum State {
141 Idle,
143 Local { owner: Arc<Shared>, key: TimerKey },
145 Remote {
147 shard: Arc<Shared>,
148 cell: Arc<RemoteTimer>,
149 },
150 Done,
152}
153
154impl<G: Grain> Timer<G> {
155 pub(super) fn new(deadline: Instant) -> Self {
156 Self {
157 deadline: Deadline::Given(deadline),
158 state: ManuallyDrop::new(State::Idle),
159 grain: PhantomData,
160 }
161 }
162
163 #[inline(always)]
167 pub(super) fn after(duration: Duration) -> Self {
168 let span = duration
169 .as_secs()
170 .checked_mul(1_000_000_000)
171 .and_then(|whole| whole.checked_add(u64::from(duration.subsec_nanos())));
172 let now = clock::now_nanos();
175 match span.and_then(|span| now.checked_add(span)) {
176 Some(at) => Self {
177 deadline: Deadline::Nanos(at),
178 state: ManuallyDrop::new(State::Idle),
179 grain: PhantomData,
180 },
181 None => Self::new(far_future()),
182 }
183 }
184
185 pub(super) fn deadline(&self) -> Instant {
187 match self.deadline {
188 Deadline::Nanos(at) => Instant::from_std(clock::instant(at)),
189 Deadline::Given(at) => at,
190 }
191 }
192
193 #[inline]
195 fn nanos(&self) -> u64 {
196 match self.deadline {
197 Deadline::Nanos(at) => at,
198 Deadline::Given(at) => clock::nanos(at.into_std()),
199 }
200 }
201
202 pub(super) fn is_elapsed(&self) -> bool {
204 matches!(*self.state, State::Done) || clock::now_nanos() >= self.nanos()
205 }
206
207 pub(super) fn reset(&mut self, deadline: Instant) {
209 self.release();
210 self.deadline = Deadline::Given(deadline);
211 }
212
213 #[inline]
215 fn release(&mut self) {
216 match *self.state {
217 State::Idle => {}
218 State::Done => *self.state = State::Idle,
220 State::Local { .. } | State::Remote { .. } => self.release_armed(),
221 }
222 }
223
224 #[inline(never)]
225 fn release_armed(&mut self) {
226 match core::mem::replace(&mut *self.state, State::Idle) {
227 State::Local { owner, key } => {
228 let here = context::current(|current| match current {
229 Some(shard) if shard.is(&owner) => {
230 shard.wheel_of(G::PRECISE).borrow_mut().remove(key);
231 true
232 }
233 _ => false,
234 });
235 if !here {
236 owner.post_timer(TimerOp::Remove {
237 key,
238 precise: G::PRECISE,
239 });
240 }
241 }
242 State::Remote { shard, cell } => {
243 cell.cancelled.store(true, Ordering::SeqCst);
244 drop(cell.waker.take());
247 shard.post_timer(TimerOp::Cancel(cell));
248 }
249 State::Idle | State::Done => {}
250 }
251 }
252
253 #[inline(always)]
254 fn poll_local(&mut self, shard: &Shard, cx: &mut Context<'_>) -> Poll<()> {
255 if let State::Local { owner, key } = &*self.state
256 && shard.is(owner)
257 {
258 let key = *key;
259 let mut wheel = shard.wheel_of(G::PRECISE).borrow_mut();
260 if wheel.is_fired(key) {
262 drop(wheel);
263 self.end_local();
264 return Poll::Ready(());
265 }
266 wheel.set_waker(key, cx.waker());
267 return Poll::Pending;
268 }
269 if let State::Remote { cell, .. } = &*self.state {
270 return poll_cell(cell, cx).map(|()| *self.state = State::Done);
271 }
272 self.release();
275 let at = self.nanos();
276 if clock::now_nanos() >= at {
277 *self.state = State::Done;
278 return Poll::Ready(());
279 }
280 let at = shard.time_of(G::PRECISE, at);
281 let mut wheel = shard.wheel_of(G::PRECISE).borrow_mut();
282 let key = wheel.insert(at, cx.waker());
283 if wheel.is_fired(key) {
284 drop(wheel);
285 *self.state = State::Done;
286 return Poll::Ready(());
287 }
288 drop(wheel);
289 *self.state = State::Local {
290 owner: Arc::clone(&shard.shared),
291 key,
292 };
293 Poll::Pending
294 }
295
296 fn poll_remote(&mut self, cx: &mut Context<'_>) -> Poll<()> {
297 if let State::Remote { cell, .. } = &*self.state {
298 return poll_cell(cell, cx).map(|()| *self.state = State::Done);
299 }
300 self.release();
301 let at = self.nanos();
302 if clock::now_nanos() >= at {
303 *self.state = State::Done;
304 return Poll::Ready(());
305 }
306 let cell = Arc::new(RemoteTimer {
307 fired: AtomicBool::new(false),
308 cancelled: AtomicBool::new(false),
309 orphaned: AtomicBool::new(false),
310 precise: G::PRECISE,
311 waker: AtomicWaker::new(),
312 key: UnsafeCell::new(None),
313 });
314 cell.waker.register(cx.waker());
315 let shard = crate::rt::runtime::service_shard();
316 shard.post_timer(TimerOp::Insert {
317 at,
318 cell: Arc::clone(&cell),
319 });
320 *self.state = State::Remote { shard, cell };
321 Poll::Pending
322 }
323
324 #[inline(always)]
326 fn end_local(&mut self) {
327 if let State::Local { owner, .. } = core::mem::replace(&mut *self.state, State::Done) {
329 drop(owner);
330 }
331 }
332
333 #[inline(always)]
334 pub(super) fn poll(&mut self, cx: &mut Context<'_>) -> Poll<()> {
335 if let State::Local { owner, key } = &*self.state
338 && let Some(shard) = context::running_inside(context::local())
339 && shard.is(owner)
340 && shard.wheel_of(G::PRECISE).borrow().is_fired(*key)
341 {
342 self.end_local();
343 return Poll::Ready(());
344 }
345 self.poll_any(cx)
346 }
347
348 #[inline(never)]
349 fn poll_any(&mut self, cx: &mut Context<'_>) -> Poll<()> {
350 if let State::Done = *self.state {
351 return Poll::Ready(());
352 }
353 if let State::Remote { cell, .. } = &*self.state
354 && cell.orphaned.load(Ordering::Acquire)
355 {
356 *self.state = State::Idle;
359 }
360 if let Some(shard) = context::running_inside(context::local()) {
363 return self.poll_local(shard, cx);
364 }
365 context::current(|current| match current {
366 Some(shard) => self.poll_local(shard, cx),
367 None => self.poll_remote(cx),
368 })
369 }
370}
371
372impl<G: Grain> Drop for Timer<G> {
373 fn drop(&mut self) {
374 if matches!(*self.state, State::Local { .. } | State::Remote { .. }) {
376 self.release_armed();
377 }
378 }
379}
380
381fn poll_cell(cell: &RemoteTimer, cx: &mut Context<'_>) -> Poll<()> {
382 if cell.fired.load(Ordering::Acquire) {
383 return Poll::Ready(());
384 }
385 cell.waker.register(cx.waker());
386 if cell.fired.load(Ordering::Acquire) {
387 Poll::Ready(())
388 } else {
389 Poll::Pending
390 }
391}
392
393pub(crate) struct RemoteTimer {
395 fired: AtomicBool,
396 cancelled: AtomicBool,
397 orphaned: AtomicBool,
400 precise: bool,
403 waker: AtomicWaker,
404 key: UnsafeCell<Option<TimerKey>>,
407}
408
409unsafe impl Send for RemoteTimer {}
413unsafe impl Sync for RemoteTimer {}
415
416impl RemoteTimer {
417 fn fire(&self) {
420 unsafe { *self.key.get() = None };
422 self.fired.store(true, Ordering::Release);
423 self.waker.wake();
424 }
425
426 pub(crate) fn orphan(&self) {
432 if self.fired.load(Ordering::Acquire) || self.cancelled.load(Ordering::SeqCst) {
433 return;
434 }
435 self.orphaned.store(true, Ordering::Release);
436 self.waker.wake();
437 }
438}
439
440struct Armed(Arc<RemoteTimer>);
443
444impl Wake for Armed {
445 fn wake(self: Arc<Self>) {
446 self.0.fire();
447 }
448
449 fn wake_by_ref(self: &Arc<Self>) {
450 self.0.fire();
451 }
452}
453
454impl Drop for Armed {
455 fn drop(&mut self) {
456 self.0.orphan();
458 }
459}
460
461pub(crate) enum TimerOp {
463 Insert { at: u64, cell: Arc<RemoteTimer> },
466 Remove { key: TimerKey, precise: bool },
470 Cancel(Arc<RemoteTimer>),
472}
473
474impl TimerOp {
475 pub(crate) fn needs_wake(&self) -> bool {
478 matches!(self, Self::Insert { .. })
479 }
480
481 pub(crate) fn orphan(self) {
484 if let Self::Insert { cell, .. } = self {
485 cell.orphan();
486 }
487 }
488
489 pub(crate) fn apply(self, shard: &Shard, wheel: &mut Wheel) {
492 match self {
493 Self::Insert { at, cell } => {
494 if cell.cancelled.load(Ordering::SeqCst) {
495 return;
496 }
497 let waker = Waker::from(Arc::new(Armed(Arc::clone(&cell))));
498 let at = shard.time_of(cell.precise, at);
499 let fired = if cell.precise {
500 arm(&mut shard.wheel_of(true).borrow_mut(), at, &waker)
501 } else {
502 arm(wheel, at, &waker)
503 };
504 match fired {
505 None => {
506 cell.fired.store(true, Ordering::Release);
507 cell.waker.wake();
508 }
509 Some(key) => unsafe { *cell.key.get() = Some(key) },
511 }
512 }
513 Self::Remove {
514 key,
515 precise: false,
516 } => wheel.remove(key),
517 Self::Remove { key, precise: true } => shard.wheel_of(true).borrow_mut().remove(key),
518 Self::Cancel(cell) => {
519 if let Some(key) = unsafe { (*cell.key.get()).take() } {
521 if cell.precise {
522 shard.wheel_of(true).borrow_mut().remove(key);
523 } else {
524 wheel.remove(key);
525 }
526 }
527 }
528 }
529 }
530}
531
532fn arm(wheel: &mut Wheel, at: u64, waker: &Waker) -> Option<TimerKey> {
535 let key = wheel.insert(at, waker);
536 (!wheel.is_fired(key)).then_some(key)
537}