sc_authority_discovery/interval.rs
1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
5
6// This program is free software: you can redistribute it and/or modify
7// it under the terms of the GNU General Public License as published by
8// the Free Software Foundation, either version 3 of the License, or
9// (at your option) any later version.
10
11// This program is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// You should have received a copy of the GNU General Public License
17// along with this program. If not, see <https://www.gnu.org/licenses/>.
18
19use futures::{future::FutureExt, ready, stream::Stream};
20use futures_timer::Delay;
21use std::{
22 pin::Pin,
23 task::{Context, Poll},
24 time::Duration,
25};
26
27/// Exponentially increasing interval
28///
29/// Doubles interval duration on each tick until the configured maximum is reached.
30pub struct ExpIncInterval {
31 start: Duration,
32 max: Duration,
33 next: Duration,
34 delay: Delay,
35}
36
37impl ExpIncInterval {
38 /// Create a new [`ExpIncInterval`].
39 pub fn new(start: Duration, max: Duration) -> Self {
40 let delay = Delay::new(start);
41 Self { start, max, next: start * 2, delay }
42 }
43
44 /// Fast forward the exponentially increasing interval to the configured maximum, if not already
45 /// set.
46 pub fn set_to_max(&mut self) {
47 if self.next == self.max {
48 return;
49 }
50
51 self.next = self.max;
52 self.delay = Delay::new(self.next);
53 }
54
55 /// Rewind the exponentially increasing interval to the configured start, if not already set.
56 pub fn set_to_start(&mut self) {
57 if self.next == self.start * 2 {
58 return;
59 }
60
61 self.next = self.start * 2;
62 self.delay = Delay::new(self.start);
63 }
64}
65
66impl Stream for ExpIncInterval {
67 type Item = ();
68
69 fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
70 ready!(self.delay.poll_unpin(cx));
71 self.delay = Delay::new(self.next);
72 self.next = std::cmp::min(self.max, self.next * 2);
73
74 Poll::Ready(Some(()))
75 }
76}