1use std::time::Duration;
3use rotor::{Machine, Scope, Response, EventSet, GenericScope, Time};
4use rotor::void::{Void, unreachable};
5
6pub struct Ticker<M: Timer> {
13 deadline: Time,
14 machine: M,
15}
16
17pub struct Interval<M: SimpleTimer>(Duration, M);
21
22pub type IntervalFunc<C> = Ticker<Interval<Box<FnMut(&mut Scope<C>) + Send>>>;
24
25pub trait Timer {
27 type Context;
28
29 fn timeout(self, scope: &mut Scope<Self::Context>) -> Self;
31
32 fn next_wakeup_time(&self, scheduled: Time,
51 scope: &mut Scope<Self::Context>)
52 -> Time;
53}
54
55pub trait SimpleTimer {
57 type Context;
58
59 fn timeout(self, scope: &mut Scope<Self::Context>) -> Self;
61}
62
63impl<T: Timer> Ticker<T> {
64 pub fn new(scope: &mut Scope<T::Context>, machine: T)
65 -> Response<Ticker<T>, Void>
66 {
67 let next = machine.next_wakeup_time(scope.now(), scope);
68 Response::ok(Ticker {
69 deadline: next,
70 machine: machine,
71 }).deadline(next)
72 }
73}
74
75impl<M: Timer> Machine for Ticker<M> {
76 type Context = M::Context;
77 type Seed = Void;
78 fn create(seed: Self::Seed, _scope: &mut Scope<Self::Context>)
79 -> Response<Self, Void>
80 {
81 unreachable(seed);
82 }
83 fn ready(self, _events: EventSet, _scope: &mut Scope<Self::Context>)
84 -> Response<Self, Self::Seed>
85 {
86 let deadline = self.deadline;
88 Response::ok(self).deadline(deadline)
89 }
90 fn spawned(self, _scope: &mut Scope<Self::Context>)
91 -> Response<Self, Self::Seed>
92 {
93 unreachable!();
94 }
95 fn timeout(self, scope: &mut Scope<Self::Context>)
96 -> Response<Self, Self::Seed>
97 {
98 let now = scope.now();
99 if now >= self.deadline {
100 let newm = self.machine.timeout(scope);
101 let next = newm.next_wakeup_time(self.deadline, scope);
102 Response::ok(Ticker {
103 deadline: next,
104 machine: newm,
105 }).deadline(next)
106 } else {
107 let deadline = self.deadline;
111 Response::ok(self).deadline(deadline)
112 }
113 }
114 fn wakeup(self, _scope: &mut Scope<Self::Context>)
115 -> Response<Self, Self::Seed>
116 {
117 let deadline = self.deadline;
119 Response::ok(self).deadline(deadline)
120 }
121}
122
123impl<T: SimpleTimer> Timer for Interval<T> {
124 type Context = T::Context;
125 fn timeout(self, scope: &mut Scope<Self::Context>) -> Self {
126 Interval(self.0, self.1.timeout(scope))
127 }
128 fn next_wakeup_time(&self, scheduled: Time,
129 scope: &mut Scope<Self::Context>)
130 -> Time
131 {
132 let goal = scheduled + self.0;
134 if scope.now() > goal {
135 return scope.now() + self.0;
137 } else {
138 return goal;
139 }
140 }
141}
142
143impl<C> SimpleTimer for Box<FnMut(&mut Scope<C>) + Send> {
144 type Context = C;
145 fn timeout(mut self, scope: &mut Scope<Self::Context>) -> Self {
146 self(scope);
147 self
148 }
149}
150
151pub fn interval_func<C, F>(scope: &mut Scope<C>, interval: Duration, fun: F)
153 -> Response<IntervalFunc<C>, Void>
154 where F: FnMut(&mut Scope<C>) + 'static + Send
155{
156 Ticker::new(scope, Interval(interval, Box::new(fun)))
157}