coven_foundation/
clock_polling.rs1use super::{Clock, FixedClock, WallTimerError};
2use std::future::Future;
3use std::pin::Pin;
4use std::sync::atomic::{AtomicBool, Ordering};
5use std::sync::{Arc, Mutex};
6use std::time::{Duration, SystemTime};
7
8pub struct PollingClock {
16 clock: Arc<FixedClock>,
17 held: AtomicBool,
21 waited: Mutex<Vec<Duration>>,
22}
23
24impl PollingClock {
25 pub fn new(clock: Arc<FixedClock>) -> Self {
27 Self { clock, held: AtomicBool::new(false), waited: Mutex::new(Vec::new()) }
28 }
29 pub fn hold_waits(&self) {
32 self.held.store(true, Ordering::SeqCst);
33 }
34 pub fn release_waits(&self) {
37 self.held.store(false, Ordering::SeqCst);
38 }
39 pub fn holds_waits(&self) -> bool {
41 self.held.load(Ordering::SeqCst)
42 }
43 pub fn waited(&self) -> Vec<Duration> {
45 crate::locks::lock_unpoisoned(&self.waited).clone()
46 }
47}
48
49impl Clock for PollingClock {
50 fn now(&self) -> SystemTime {
51 self.clock.now()
52 }
53 fn elapsed(&self) -> Duration {
54 self.clock.elapsed()
55 }
56 fn deadline(&self, duration: Duration) -> Pin<Box<dyn Future<Output = ()> + Send>> {
57 self.clock.deadline(duration)
58 }
59 fn wait_out(&self, wait: Duration) -> Pin<Box<dyn Future<Output = ()> + Send>> {
60 crate::locks::lock_unpoisoned(&self.waited).push(wait);
61 let woken = self.clock.wait_out(wait);
62 if self.held.load(Ordering::SeqCst) {
63 return woken;
64 }
65 let end = self.clock.elapsed() + wait;
66 let clock = self.clock.clone();
67 Box::pin(async move {
68 let left = end.saturating_sub(clock.elapsed());
69 if !left.is_zero() {
70 clock.set(clock.now() + left);
71 }
72 woken.await;
73 })
74 }
75 fn sleep_until(
76 &self,
77 at: SystemTime,
78 ) -> Pin<Box<dyn Future<Output = Result<(), WallTimerError>> + Send>> {
79 self.clock.sleep_until(at)
80 }
81}