actix_server/
availability.rs

1use crate::worker::WorkerHandleAccept;
2
3/// Array of u128 with every bit as marker for a worker handle's availability.
4#[derive(Debug, Default)]
5pub(crate) struct Availability([u128; 4]);
6
7impl Availability {
8    /// Check if any worker handle is available
9    #[inline(always)]
10    pub(crate) fn available(&self) -> bool {
11        self.0.iter().any(|a| *a != 0)
12    }
13
14    /// Check if worker handle is available by index
15    #[inline(always)]
16    pub(crate) fn get_available(&self, idx: usize) -> bool {
17        let (offset, idx) = Self::offset(idx);
18
19        self.0[offset] & (1 << idx as u128) != 0
20    }
21
22    /// Set worker handle available state by index.
23    pub(crate) fn set_available(&mut self, idx: usize, avail: bool) {
24        let (offset, idx) = Self::offset(idx);
25
26        let off = 1 << idx as u128;
27        if avail {
28            self.0[offset] |= off;
29        } else {
30            self.0[offset] &= !off
31        }
32    }
33
34    /// Set all worker handle to available state.
35    /// This would result in a re-check on all workers' availability.
36    pub(crate) fn set_available_all(&mut self, handles: &[WorkerHandleAccept]) {
37        handles.iter().for_each(|handle| {
38            self.set_available(handle.idx(), true);
39        })
40    }
41
42    /// Get offset and adjusted index of given worker handle index.
43    pub(crate) fn offset(idx: usize) -> (usize, usize) {
44        if idx < 128 {
45            (0, idx)
46        } else if idx < 128 * 2 {
47            (1, idx - 128)
48        } else if idx < 128 * 3 {
49            (2, idx - 128 * 2)
50        } else if idx < 128 * 4 {
51            (3, idx - 128 * 3)
52        } else {
53            panic!("Max WorkerHandle count is 512")
54        }
55    }
56}
57
58#[cfg(test)]
59mod tests {
60    use super::*;
61
62    fn single(aval: &mut Availability, idx: usize) {
63        aval.set_available(idx, true);
64        assert!(aval.available());
65
66        aval.set_available(idx, true);
67
68        aval.set_available(idx, false);
69        assert!(!aval.available());
70
71        aval.set_available(idx, false);
72        assert!(!aval.available());
73    }
74
75    fn multi(aval: &mut Availability, mut idx: Vec<usize>) {
76        idx.iter().for_each(|idx| aval.set_available(*idx, true));
77
78        assert!(aval.available());
79
80        while let Some(idx) = idx.pop() {
81            assert!(aval.available());
82            aval.set_available(idx, false);
83        }
84
85        assert!(!aval.available());
86    }
87
88    #[test]
89    fn availability() {
90        let mut aval = Availability::default();
91
92        single(&mut aval, 1);
93        single(&mut aval, 128);
94        single(&mut aval, 256);
95        single(&mut aval, 511);
96
97        let idx = (0..511).filter(|i| i % 3 == 0 && i % 5 == 0).collect();
98
99        multi(&mut aval, idx);
100
101        multi(&mut aval, (0..511).collect())
102    }
103
104    #[test]
105    #[should_panic]
106    fn overflow() {
107        let mut aval = Availability::default();
108        single(&mut aval, 512);
109    }
110
111    #[test]
112    fn pin_point() {
113        let mut aval = Availability::default();
114
115        aval.set_available(438, true);
116
117        aval.set_available(479, true);
118
119        assert_eq!(aval.0[3], 1 << (438 - 384) | 1 << (479 - 384));
120    }
121}