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}