fast_steal/
task.rs

1use core::{
2    hash::Hash,
3    ops::Range,
4    sync::atomic::{AtomicU64, Ordering},
5};
6
7#[derive(Debug)]
8pub struct Task {
9    start: AtomicU64,
10    end: AtomicU64,
11}
12
13impl Task {
14    pub fn remain(&self) -> u64 {
15        let start = self.start();
16        let end = self.end();
17        end.saturating_sub(start)
18    }
19
20    pub fn start(&self) -> u64 {
21        self.start.load(Ordering::Acquire)
22    }
23    pub fn set_start(&self, start: u64) {
24        self.start.store(start, Ordering::Release);
25    }
26    pub fn fetch_add_start(&self, value: u64) -> u64 {
27        self.start.fetch_add(value, Ordering::AcqRel)
28    }
29    pub fn fetch_sub_start(&self, value: u64) -> u64 {
30        self.start.fetch_sub(value, Ordering::AcqRel)
31    }
32    pub fn end(&self) -> u64 {
33        self.end.load(Ordering::Acquire)
34    }
35    pub fn set_end(&self, end: u64) {
36        self.end.store(end, Ordering::Release);
37    }
38    pub fn fetch_add_end(&self, value: u64) -> u64 {
39        self.end.fetch_add(value, Ordering::AcqRel)
40    }
41    pub fn fetch_sub_end(&self, value: u64) -> u64 {
42        self.end.fetch_sub(value, Ordering::AcqRel)
43    }
44
45    pub fn new(start: u64, end: u64) -> Self {
46        Self {
47            start: AtomicU64::new(start),
48            end: AtomicU64::new(end),
49        }
50    }
51}
52
53impl PartialEq for Task {
54    fn eq(&self, other: &Self) -> bool {
55        self.start() == other.start() && self.end() == other.end()
56    }
57}
58impl Eq for Task {}
59impl PartialOrd for Task {
60    fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
61        Some(self.cmp(other))
62    }
63}
64impl Ord for Task {
65    fn cmp(&self, other: &Self) -> core::cmp::Ordering {
66        self.remain().cmp(&other.remain())
67    }
68}
69impl Hash for Task {
70    fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
71        self.start().hash(state);
72        self.end().hash(state);
73    }
74}
75
76impl From<&(u64, u64)> for Task {
77    fn from(value: &(u64, u64)) -> Self {
78        Self::new(value.0, value.1)
79    }
80}
81
82impl From<&Range<u64>> for Task {
83    fn from(value: &Range<u64>) -> Self {
84        Self::new(value.start, value.end)
85    }
86}
87
88#[cfg(test)]
89mod tests {
90    use super::*;
91
92    #[test]
93    fn test_new_task() {
94        let task = Task::new(10, 20);
95        assert_eq!(task.start(), 10);
96        assert_eq!(task.end(), 20);
97        assert_eq!(task.remain(), 10);
98    }
99
100    #[test]
101    fn test_from_tuple() {
102        let task: Task = (&(5, 15)).into();
103        assert_eq!(task.start(), 5);
104        assert_eq!(task.end(), 15);
105    }
106
107    #[test]
108    fn test_from_range() {
109        let range = 3..8;
110        let task: Task = (&range).into();
111        assert_eq!(task.start(), range.start);
112        assert_eq!(task.end(), range.end);
113    }
114
115    #[test]
116    fn test_setters() {
117        let task = Task::new(0, 0);
118        task.set_start(7);
119        task.set_end(14);
120        assert_eq!(task.start(), 7);
121        assert_eq!(task.end(), 14);
122    }
123
124    #[test]
125    fn test_remain() {
126        let task = Task::new(10, 25);
127        assert_eq!(task.remain(), 15);
128
129        task.set_start(20);
130        assert_eq!(task.remain(), 5);
131    }
132
133    #[test]
134    fn test_partial_eq() {
135        let task1 = Task::new(1, 10);
136        let task2 = Task::new(1, 10);
137        let task3 = Task::new(2, 10);
138        let task4 = Task::new(1, 11);
139
140        assert_eq!(task1, task2);
141        assert_ne!(task1, task3);
142        assert_ne!(task1, task4);
143    }
144}