Skip to main content

gsfw_util/timer/
timer.rs

1use futures::{ready, Future, FutureExt};
2use pin_project::pin_project;
3use std::{
4    pin::Pin,
5    sync::atomic::{AtomicU64, Ordering},
6};
7
8static TIMER_ID: AtomicU64 = AtomicU64::new(1);
9
10#[derive(Debug)]
11pub struct Snapshot {
12    pub id: u64,
13    pub start: std::time::Instant,
14    pub end: std::time::Instant,
15}
16
17#[derive(Debug)]
18pub struct Meta<T> {
19    pub id: u64,
20    pub start: std::time::Instant,
21    pub end: std::time::Instant,
22    pub data: Option<T>,
23}
24
25impl<T> Meta<T> {
26    pub fn new(start: std::time::Instant, end: std::time::Instant, data: T) -> Self {
27        Self {
28            id: TIMER_ID.fetch_add(1, Ordering::Acquire),
29            start,
30            end,
31            data: Some(data),
32        }
33    }
34}
35
36#[pin_project]
37pub struct Timer<T> {
38    meta: Meta<T>,
39    sleep: Pin<Box<tokio::time::Sleep>>,
40}
41
42impl<T> Timer<T>
43where
44    T: 'static,
45{
46    pub fn new(start: std::time::Instant, end: std::time::Instant, data: T) -> Self {
47        Self {
48            sleep: Box::pin(tokio::time::sleep_until(end.into())),
49            meta: Meta {
50                id: TIMER_ID.fetch_add(1, Ordering::Acquire),
51                start,
52                end,
53                data: Some(data),
54            },
55        }
56    }
57}
58
59impl<T> Future for Timer<T> {
60    type Output = Result<T, super::Error<T>>;
61
62    fn poll(
63        self: std::pin::Pin<&mut Self>,
64        cx: &mut std::task::Context<'_>,
65    ) -> std::task::Poll<Self::Output> {
66        let this = self.project();
67        ready!(this.sleep.poll_unpin(cx));
68        if this.meta.data.is_none() {
69            return std::task::Poll::Ready(Err(super::Error::TimerFinish));
70        }
71        let data = this.meta.data.take().unwrap();
72        std::task::Poll::Ready(Ok(data))
73    }
74}