libp2p_mdns/behaviour/
timer.rs

1// Copyright 2018 Parity Technologies (UK) Ltd.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a
4// copy of this software and associated documentation files (the "Software"),
5// to deal in the Software without restriction, including without limitation
6// the rights to use, copy, modify, merge, publish, distribute, sublicense,
7// and/or sell copies of the Software, and to permit persons to whom the
8// Software is furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in
11// all copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
14// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
19// DEALINGS IN THE SOFTWARE.
20
21use std::time::{Duration, Instant};
22
23/// Simple wrapper for the different type of timers
24#[derive(Debug)]
25#[cfg(feature = "tokio")]
26pub struct Timer<T> {
27    inner: T,
28}
29
30/// Builder interface to homogenize the different implementations
31#[allow(unreachable_pub)] // Users should not depend on this.
32pub trait Builder: Send + Unpin + 'static {
33    /// Creates a timer that emits an event once at the given time instant.
34    fn at(instant: Instant) -> Self;
35
36    /// Creates a timer that emits events periodically.
37    fn interval(duration: Duration) -> Self;
38
39    /// Creates a timer that emits events periodically, starting at start.
40    fn interval_at(start: Instant, duration: Duration) -> Self;
41}
42
43#[cfg(feature = "tokio")]
44pub(crate) mod tokio {
45    use std::{
46        pin::Pin,
47        task::{Context, Poll},
48    };
49
50    use ::tokio::time::{self, Instant as TokioInstant, Interval, MissedTickBehavior};
51    use futures::Stream;
52
53    use super::*;
54
55    /// Tokio wrapper
56    pub(crate) type TokioTimer = Timer<Interval>;
57    impl Builder for TokioTimer {
58        fn at(instant: Instant) -> Self {
59            // Taken from: https://docs.rs/async-io/1.7.0/src/async_io/lib.rs.html#91
60            let mut inner = time::interval_at(
61                TokioInstant::from_std(instant),
62                Duration::new(u64::MAX, 1_000_000_000 - 1),
63            );
64            inner.set_missed_tick_behavior(MissedTickBehavior::Skip);
65            Self { inner }
66        }
67
68        fn interval(duration: Duration) -> Self {
69            let mut inner = time::interval_at(TokioInstant::now() + duration, duration);
70            inner.set_missed_tick_behavior(MissedTickBehavior::Skip);
71            Self { inner }
72        }
73
74        fn interval_at(start: Instant, duration: Duration) -> Self {
75            let mut inner = time::interval_at(TokioInstant::from_std(start), duration);
76            inner.set_missed_tick_behavior(MissedTickBehavior::Skip);
77            Self { inner }
78        }
79    }
80
81    impl Stream for TokioTimer {
82        type Item = TokioInstant;
83
84        fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
85            self.inner.poll_tick(cx).map(Some)
86        }
87
88        fn size_hint(&self) -> (usize, Option<usize>) {
89            (usize::MAX, None)
90        }
91    }
92}