1use std::sync::atomic::{AtomicBool, Ordering};
2use std::sync::Arc;
3use tokio::sync::Notify;
4
5pub struct EventFlagSet {
10 flags: Vec<AtomicBool>,
11 sync_map: Vec<Vec<usize>>,
13 ss_wakeups: Vec<Arc<Notify>>,
15}
16
17impl EventFlagSet {
18 pub fn new(
19 num_flags: usize,
20 sync_map: Vec<Vec<usize>>,
21 ss_wakeups: Vec<Arc<Notify>>,
22 ) -> Self {
23 let flags = (0..num_flags).map(|_| AtomicBool::new(false)).collect();
24 Self {
25 flags,
26 sync_map,
27 ss_wakeups,
28 }
29 }
30
31 pub fn set(&self, ef_id: usize) {
33 if let Some(flag) = self.flags.get(ef_id) {
34 flag.store(true, Ordering::Release);
35 for notify in &self.ss_wakeups {
36 notify.notify_one();
37 }
38 }
39 }
40
41 pub fn test(&self, ef_id: usize) -> bool {
43 self.flags
44 .get(ef_id)
45 .map_or(false, |f| f.load(Ordering::Acquire))
46 }
47
48 pub fn clear(&self, ef_id: usize) -> bool {
50 self.flags
51 .get(ef_id)
52 .map_or(false, |f| f.swap(false, Ordering::AcqRel))
53 }
54
55 pub fn test_and_clear(&self, ef_id: usize) -> bool {
57 self.flags
58 .get(ef_id)
59 .map_or(false, |f| f.swap(false, Ordering::AcqRel))
60 }
61
62 pub fn synced_channels(&self, ef_id: usize) -> &[usize] {
64 self.sync_map.get(ef_id).map_or(&[], |v| v.as_slice())
65 }
66
67 pub fn num_flags(&self) -> usize {
68 self.flags.len()
69 }
70}
71
72#[cfg(test)]
73mod tests {
74 use super::*;
75
76 fn make_efs(num_flags: usize, sync_map: Vec<Vec<usize>>, num_ss: usize) -> EventFlagSet {
77 let wakeups = (0..num_ss).map(|_| Arc::new(Notify::new())).collect();
78 EventFlagSet::new(num_flags, sync_map, wakeups)
79 }
80
81 #[test]
82 fn test_set_and_test() {
83 let efs = make_efs(3, vec![vec![]; 3], 1);
84 assert!(!efs.test(0));
85 efs.set(0);
86 assert!(efs.test(0));
87 assert!(!efs.test(1));
88 }
89
90 #[test]
91 fn test_clear() {
92 let efs = make_efs(2, vec![vec![]; 2], 1);
93 efs.set(0);
94 assert!(efs.clear(0));
95 assert!(!efs.test(0));
96 assert!(!efs.clear(0));
98 }
99
100 #[test]
101 fn test_test_and_clear() {
102 let efs = make_efs(2, vec![vec![]; 2], 1);
103 efs.set(1);
104 assert!(efs.test_and_clear(1));
105 assert!(!efs.test(1));
106 assert!(!efs.test_and_clear(1));
107 }
108
109 #[test]
110 fn test_synced_channels() {
111 let efs = make_efs(2, vec![vec![0, 1], vec![2]], 1);
112 assert_eq!(efs.synced_channels(0), &[0, 1]);
113 assert_eq!(efs.synced_channels(1), &[2]);
114 }
115
116 #[test]
117 fn test_invalid_flag_id() {
118 let efs = make_efs(1, vec![vec![]], 1);
119 assert!(!efs.test(99));
120 assert!(!efs.clear(99));
121 assert!(!efs.test_and_clear(99));
122 assert_eq!(efs.synced_channels(99), &[] as &[usize]);
123 }
124}