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}