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}