1use fuchsia_async as fasync;
6use futures::channel::mpsc;
7use futures::{FutureExt, Stream, StreamExt};
8use std::sync::{Arc, atomic};
9use zx;
10
11use crate::sink::UnboundedSink;
12
13pub type ScheduledEvent<E> = (zx::MonotonicInstant, Event<E>, EventHandle);
14pub type EventSender<E> = UnboundedSink<ScheduledEvent<E>>;
15pub type EventStream<E> = mpsc::UnboundedReceiver<ScheduledEvent<E>>;
16pub type EventId = u64;
17
18pub fn create_timer<E>() -> (Timer<E>, EventStream<E>) {
22 let (timer_sink, time_stream) = mpsc::unbounded();
23 (Timer::new(UnboundedSink::new(timer_sink)), time_stream)
24}
25
26pub fn make_async_timed_event_stream<E>(
27 time_stream: impl Stream<Item = ScheduledEvent<E>>,
28) -> impl Stream<Item = Event<E>> {
29 Box::pin(
32 time_stream
33 .map(|(deadline, timed_event, handle)| {
34 fasync::Timer::new(fasync::MonotonicInstant::from_zx(deadline))
35 .map(|_| (timed_event, handle))
36 })
37 .buffer_unordered(usize::MAX)
38 .filter_map(|(timed_event, handle)| async move {
39 if handle.is_active() { Some(timed_event) } else { None }
40 }),
41 )
42}
43
44#[derive(Debug)]
45pub struct Event<E> {
46 pub id: EventId,
47 pub event: E,
48}
49
50impl<E: Clone> Clone for Event<E> {
51 fn clone(&self) -> Self {
52 Event { id: self.id, event: self.event.clone() }
53 }
54}
55
56#[derive(Debug)]
57pub struct Timer<E> {
58 sender: EventSender<E>,
59 next_id: EventId,
60}
61
62impl<E> Timer<E> {
63 pub fn new(sender: EventSender<E>) -> Self {
64 Timer { sender, next_id: 0 }
65 }
66
67 pub fn now(&self) -> zx::MonotonicInstant {
73 fasync::MonotonicInstant::now().into_zx()
75 }
76
77 pub fn schedule_at(&mut self, deadline: zx::MonotonicInstant, event: E) -> EventHandle {
78 let id = self.next_id;
79 let timer_handle = EventHandle::new(id);
80 let inner_handle = EventHandle {
81 active: Arc::clone(&timer_handle.active),
82 event_id: id,
83 cancel_on_drop: true,
86 };
87 self.sender.send((deadline, Event { id, event }, inner_handle));
88 self.next_id += 1;
89 timer_handle
90 }
91
92 pub fn schedule_after(&mut self, duration: zx::MonotonicDuration, event: E) -> EventHandle {
93 self.schedule_at(fasync::MonotonicInstant::after(duration).into_zx(), event)
94 }
95
96 pub fn schedule<EV>(&mut self, event: EV) -> EventHandle
97 where
98 EV: TimeoutDuration + Into<E>,
99 {
100 self.schedule_after(event.timeout_duration(), event.into())
101 }
102}
103
104pub trait TimeoutDuration {
105 fn timeout_duration(&self) -> zx::MonotonicDuration;
106}
107
108#[derive(Debug)]
112pub struct EventHandle {
113 active: Arc<atomic::AtomicBool>,
114 event_id: EventId,
115 cancel_on_drop: bool,
116}
117
118impl EventHandle {
119 fn new(event_id: EventId) -> Self {
120 Self { active: Arc::new(atomic::AtomicBool::new(true)), event_id, cancel_on_drop: true }
121 }
122
123 pub fn new_test(event_id: EventId) -> Self {
126 Self::new(event_id)
127 }
128
129 fn is_active(&self) -> bool {
131 self.active.load(atomic::Ordering::Acquire)
132 }
133
134 pub fn id(&self) -> EventId {
136 self.event_id
137 }
138
139 pub fn drop_without_cancel(mut self) {
143 self.cancel_on_drop = false;
144 }
145}
146
147impl std::ops::Drop for EventHandle {
148 fn drop(&mut self) {
149 if self.cancel_on_drop {
150 self.active.store(false, atomic::Ordering::Release);
151 }
152 }
153}
154
155#[cfg(test)]
156mod tests {
157 use super::*;
158 use assert_matches::assert_matches;
159 use fuchsia_async as fasync;
160
161 use futures::channel::mpsc::UnboundedSender;
162 use std::pin::pin;
163 use std::task::Poll;
164
165 type TestEvent = u32;
166 impl TimeoutDuration for TestEvent {
167 fn timeout_duration(&self) -> zx::MonotonicDuration {
168 zx::MonotonicDuration::from_seconds(10)
169 }
170 }
171
172 #[test]
173 fn test_timer_schedule_at() {
174 let _exec = fasync::TestExecutor::new();
175 let (mut timer, mut time_stream) = create_timer::<TestEvent>();
176 let timeout1 = zx::MonotonicInstant::after(zx::MonotonicDuration::from_seconds(5));
177 let timeout2 = zx::MonotonicInstant::after(zx::MonotonicDuration::from_seconds(10));
178 let event_handle1 = timer.schedule_at(timeout1, 7);
179 let event_handle2 = timer.schedule_at(timeout2, 9);
180 assert_eq!(event_handle1.id(), 0);
181 assert_eq!(event_handle2.id(), 1);
182
183 let (t1, event1, _) = time_stream.try_recv().expect("expect time entry");
184 assert_eq!(t1, timeout1);
185 assert_eq!(event1.id, 0);
186 assert_eq!(event1.event, 7);
187
188 let (t2, event2, _) = time_stream.try_recv().expect("expect time entry");
189 assert_eq!(t2, timeout2);
190 assert_eq!(event2.id, 1);
191 assert_eq!(event2.event, 9);
192
193 assert_matches!(time_stream.try_recv(), Err(e) => {
194 assert_eq!(e.to_string(), "receive failed because channel is empty")
195 });
196 }
197
198 #[test]
199 fn test_timer_schedule_after() {
200 let _exec = fasync::TestExecutor::new();
201 let (mut timer, mut time_stream) = create_timer::<TestEvent>();
202 let timeout1 = zx::MonotonicDuration::from_seconds(1000);
203 let timeout2 = zx::MonotonicDuration::from_seconds(5);
204 let event_handle1 = timer.schedule_after(timeout1, 7);
205 let event_handle2 = timer.schedule_after(timeout2, 9);
206 assert_eq!(event_handle1.id(), 0);
207 assert_eq!(event_handle2.id(), 1);
208
209 let (t1, event1, _) = time_stream.try_recv().expect("expect time entry");
210 assert_eq!(event1.id, 0);
211 assert_eq!(event1.event, 7);
212
213 let (t2, event2, _) = time_stream.try_recv().expect("expect time entry");
214 assert_eq!(event2.id, 1);
215 assert_eq!(event2.event, 9);
216
217 assert!(t1.into_nanos() > t2.into_nanos());
220
221 assert_matches!(time_stream.try_recv(), Err(e) => {
222 assert_eq!(e.to_string(), "receive failed because channel is empty")
223 });
224 }
225
226 #[test]
227 fn test_timer_schedule() {
228 let _exec = fasync::TestExecutor::new();
229 let (mut timer, mut time_stream) = create_timer::<TestEvent>();
230 let start = zx::MonotonicInstant::after(zx::MonotonicDuration::from_millis(0));
231
232 let event_handle = timer.schedule(5u32);
233 assert_eq!(event_handle.id(), 0);
234
235 let (t, event, _) = time_stream.try_recv().expect("expect time entry");
236 assert_eq!(event.id, 0);
237 assert_eq!(event.event, 5);
238 assert!(start + zx::MonotonicDuration::from_seconds(10) <= t);
239 }
240
241 #[test]
242 fn test_timer_stream() {
243 let mut exec = fasync::TestExecutor::new_with_fake_time();
244 let fut = async {
245 let (timer, time_stream) = mpsc::unbounded::<ScheduledEvent<TestEvent>>();
246 let mut timeout_stream = make_async_timed_event_stream(time_stream);
247 let now = zx::MonotonicInstant::get();
248 let _handle1 = schedule(&timer, now + zx::MonotonicDuration::from_millis(40), 0);
249 let _handle2 = schedule(&timer, now + zx::MonotonicDuration::from_millis(10), 1);
250 let _handle3 = schedule(&timer, now + zx::MonotonicDuration::from_millis(20), 2);
251 let _handle4 = schedule(&timer, now + zx::MonotonicDuration::from_millis(30), 3);
252
253 let mut events = vec![];
254 for _ in 0u32..4 {
255 let event = timeout_stream.next().await.expect("timer terminated prematurely");
256 events.push(event.event);
257 }
258 events
259 };
260 let mut fut = pin!(fut);
261 for _ in 0u32..4 {
262 assert_eq!(Poll::Pending, exec.run_until_stalled(&mut fut));
263 assert!(exec.wake_next_timer().is_some());
264 }
265 assert_matches!(
266 exec.run_until_stalled(&mut fut),
267 Poll::Ready(events) => assert_eq!(events, vec![1, 2, 3, 0])
268 );
269 }
270
271 #[test]
272 fn test_timer_stream_cancel() {
273 let mut exec = fasync::TestExecutor::new_with_fake_time();
274 let (mut timer, time_stream) = create_timer::<TestEvent>();
275 let mut timeout_stream = make_async_timed_event_stream(time_stream);
276
277 let deadline = zx::MonotonicInstant::after(zx::Duration::from_seconds(5));
278
279 {
280 let _event_handle = timer.schedule_at(deadline, 0);
282 }
283
284 exec.set_fake_time(deadline.into());
285 let mut next = timeout_stream.next();
286 assert_matches!(exec.run_until_stalled(&mut next), Poll::Pending);
287 }
288
289 #[test]
290 fn test_timer_stream_drop_without_cancel() {
291 let mut exec = fasync::TestExecutor::new_with_fake_time();
292 let (mut timer, time_stream) = create_timer::<TestEvent>();
293 let mut timeout_stream = make_async_timed_event_stream(time_stream);
294
295 let deadline = zx::MonotonicInstant::after(zx::Duration::from_seconds(5));
296
297 {
298 timer.schedule_at(deadline, 7357).drop_without_cancel();
300 }
301
302 exec.set_fake_time(deadline.into());
303 let mut next = timeout_stream.next();
304 let event =
306 assert_matches!(exec.run_until_stalled(&mut next), Poll::Ready(Some(event)) => event);
307 assert_eq!(event.event, 7357);
308 }
309
310 fn schedule(
311 timer: &UnboundedSender<ScheduledEvent<TestEvent>>,
312 deadline: zx::MonotonicInstant,
313 event: TestEvent,
314 ) -> EventHandle {
315 let id = 0;
316 let handle = EventHandle::new(id);
317 let inner_handle =
318 EventHandle { active: Arc::clone(&handle.active), event_id: id, cancel_on_drop: true };
319 let entry = (deadline, Event { id, event }, inner_handle);
320 timer.unbounded_send(entry).expect("expect send successful");
321 handle
322 }
323}