1
// Copyright (C) Parity Technologies (UK) Ltd.
2
// This file is part of Polkadot.
3

            
4
// Polkadot is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8

            
9
// Polkadot is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13

            
14
// You should have received a copy of the GNU General Public License
15
// along with Polkadot.  If not, see <http://www.gnu.org/licenses/>.
16

            
17
use futures::prelude::*;
18
use futures_timer::Delay;
19
use std::{
20
	pin::Pin,
21
	task::{Context, Poll},
22
	time::Duration,
23
};
24

            
25
#[derive(Copy, Clone)]
26
enum MetronomeState {
27
	Snooze,
28
	SetAlarm,
29
}
30

            
31
/// Create a stream of ticks with a defined cycle duration.
32
pub struct Metronome {
33
	delay: Delay,
34
	period: Duration,
35
	state: MetronomeState,
36
}
37

            
38
impl Metronome {
39
	/// Create a new metronome source with a defined cycle duration.
40
	pub fn new(cycle: Duration) -> Self {
41
		let period = cycle.into();
42
		Self { period, delay: Delay::new(period), state: MetronomeState::Snooze }
43
	}
44
}
45

            
46
impl futures::Stream for Metronome {
47
	type Item = ();
48
	fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
49
		loop {
50
			match self.state {
51
				MetronomeState::SetAlarm => {
52
					let val = self.period;
53
					self.delay.reset(val);
54
					self.state = MetronomeState::Snooze;
55
				},
56
				MetronomeState::Snooze => {
57
					if !Pin::new(&mut self.delay).poll(cx).is_ready() {
58
						break
59
					}
60
					self.state = MetronomeState::SetAlarm;
61
					return Poll::Ready(Some(()))
62
				},
63
			}
64
		}
65
		Poll::Pending
66
	}
67
}