1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
use event_listener::{Event, EventListener};

#[must_use = "TimeHandlerGuard must be kept until the timer has performed it's side-effects"]
pub struct TimeHandlerGuard(Event);

impl TimeHandlerGuard {
	pub(crate) fn new() -> (Self, TimeHandlerFinished) {
		let event = Event::new();
		let listener = event.listen();
		(Self(event), TimeHandlerFinished(listener))
	}
}

impl Drop for TimeHandlerGuard {
	fn drop(&mut self) {
		self.0.notify(1);
	}
}

pub(crate) struct TimeHandlerFinished(EventListener);

impl TimeHandlerFinished {
	pub(crate) async fn wait(self) {
		self.0.await
	}
}

#[cfg(test)]
mod test {
	use crate::TimeHandlerGuard;
	use futures_lite::future::poll_once;
	use futures_lite::pin;

	#[tokio::test]
	async fn should_notify_once_time_handler_guard_is_dropped() {
		let (guard, waiter) = TimeHandlerGuard::new();

		let waiter_future = waiter.wait();
		pin!(waiter_future);
		assert!(
			poll_once(waiter_future.as_mut()).await.is_none(),
			"Waiter should have been pending before the guard is dropped",
		);

		drop(guard);
		assert!(
			poll_once(waiter_future.as_mut()).await.is_some(),
			"Waiter should have been ready after the guard was dropped",
		);
	}
}