bach/time/
entry.rs

1pub trait Entry: Sized {
2    type Queue: Queue<Self>;
3
4    fn delay(&self) -> u64;
5    fn start_tick(&self) -> u64;
6    fn set_start_tick(&mut self, tick: u64);
7}
8
9pub trait Queue<Entry> {
10    fn new() -> Self;
11    fn is_empty(&self) -> bool;
12    fn push(&mut self, entry: Entry);
13    fn pop(&mut self) -> Option<Entry>;
14    fn take(&mut self) -> Self;
15}
16
17pub mod atomic {
18    use super::*;
19    use alloc::sync::Arc;
20    use atomic_waker::AtomicWaker;
21    use core::{
22        sync::atomic::{AtomicBool, AtomicU64, Ordering},
23        task::Waker,
24    };
25    use intrusive_collections::{intrusive_adapter, LinkedList, LinkedListLink};
26
27    intrusive_adapter!(pub Adapter = ArcEntry: Entry { link: LinkedListLink });
28
29    pub type ArcEntry = Arc<Entry>;
30
31    #[derive(Debug)]
32    pub struct Entry {
33        waker: AtomicWaker,
34        expired: AtomicBool,
35        registered: AtomicBool,
36        delay: u64,
37        start_tick: AtomicU64,
38        link: LinkedListLink,
39    }
40
41    unsafe impl Send for Entry {}
42    unsafe impl Sync for Entry {}
43
44    pub fn wake(entry: ArcEntry) {
45        entry.wake();
46    }
47
48    impl Entry {
49        pub fn new(delay: u64) -> Arc<Self> {
50            Arc::new(Self {
51                waker: AtomicWaker::new(),
52                expired: AtomicBool::new(false),
53                registered: AtomicBool::new(false),
54                delay,
55                start_tick: AtomicU64::new(0),
56                link: LinkedListLink::new(),
57            })
58        }
59
60        pub fn wake(&self) {
61            self.expired.store(true, Ordering::SeqCst);
62            self.registered.store(false, Ordering::SeqCst);
63
64            if let Some(waker) = self.waker.take() {
65                waker.wake();
66            }
67        }
68
69        pub fn should_register(&self) -> bool {
70            !self.registered.swap(true, Ordering::SeqCst)
71        }
72
73        pub fn cancel(&self) {
74            self.waker.take();
75        }
76
77        pub fn take_expired(&self) -> bool {
78            self.expired.swap(false, Ordering::SeqCst)
79        }
80
81        pub fn register(&self, waker: &Waker) {
82            self.waker.register(waker)
83        }
84    }
85
86    impl super::Entry for Arc<Entry> {
87        type Queue = LinkedList<Adapter>;
88
89        fn delay(&self) -> u64 {
90            self.delay
91        }
92
93        fn start_tick(&self) -> u64 {
94            self.start_tick.load(Ordering::SeqCst)
95        }
96
97        fn set_start_tick(&mut self, tick: u64) {
98            self.start_tick.store(tick, Ordering::SeqCst);
99        }
100    }
101
102    impl Drop for Entry {
103        fn drop(&mut self) {
104            self.cancel();
105        }
106    }
107
108    impl Queue<ArcEntry> for LinkedList<Adapter> {
109        fn new() -> Self {
110            LinkedList::new(Adapter::new())
111        }
112
113        fn is_empty(&self) -> bool {
114            LinkedList::is_empty(self)
115        }
116
117        fn push(&mut self, entry: ArcEntry) {
118            self.push_back(entry);
119        }
120
121        fn pop(&mut self) -> Option<ArcEntry> {
122            self.pop_front()
123        }
124
125        fn take(&mut self) -> Self {
126            LinkedList::take(self)
127        }
128    }
129}