1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
//! syscall for timeout.

use std::{
    io,
    sync::OnceLock,
    task::{Poll, Waker},
    time::Instant,
};

use crate::handle::Handle;

/// Timer-related system call interface
pub trait Timer: Send + Sync {
    /// Create new `deadline` timer, returns [`None`] if the `deadline` instant is reached.
    fn deadline(&self, waker: Waker, deadline: Instant) -> io::Result<Option<Handle>>;

    /// Wait timeout event.
    ///
    /// Returns [`Poll::Ready(())`](Poll::Ready) if the timer already reached the deadline,
    /// otherwise returns [`Poll::Pending`] and needs to be retried later.
    ///
    /// We don't need to return [`CancelablePoll`](crate::CancelablePoll),
    /// because the implementation should stop the timer when the timer handler drops.
    fn timeout_wait(&self, waker: Waker, handle: &Handle) -> Poll<()>;
}

static GLOBAL_TIMER: OnceLock<Box<dyn Timer>> = OnceLock::new();

/// Register provided [`Timer`] as global timer implementation.
///
/// # Panic
///
/// Multiple calls to this function are not permitted!!!
pub fn register_global_timer<T: Timer + 'static>(timer: T) {
    if GLOBAL_TIMER.set(Box::new(timer)).is_err() {
        panic!("Multiple calls to register_global_timer are not permitted!!!");
    }
}

/// Get the globally registered instance of [`Timer`].
///
/// # Panic
///
/// You should call [`register_global_timer`] first to register implementation,
/// otherwise this function will cause a panic with `Call register_global_timer first`
pub fn global_timer() -> &'static dyn Timer {
    GLOBAL_TIMER
        .get()
        .expect("Call register_global_timer first")
        .as_ref()
}