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}