shuttle_engine/runtime/task/
clock.rs1use crate::runtime::task::TaskId;
2use std::cmp::{Ordering, PartialOrd};
3
4#[cfg(all(any(test, feature = "vector-clocks"), not(feature = "bench-no-vector-clocks")))]
5mod vector_clock {
6 use super::*;
7 use crate::runtime::task::DEFAULT_INLINE_TASKS;
8 use smallvec::{smallvec, SmallVec};
9
10 #[derive(Clone, Debug, PartialEq, Eq)]
11 pub struct VectorClock {
12 pub time: SmallVec<[u32; DEFAULT_INLINE_TASKS]>,
13 }
14
15 impl VectorClock {
16 pub const fn new() -> Self {
17 Self {
18 time: SmallVec::new_const(),
19 }
20 }
21
22 pub fn extend(&mut self, task_id: TaskId) {
24 let num_new_tasks = 1 + task_id.0 - self.time.len();
25 let clock: SmallVec<[_; DEFAULT_INLINE_TASKS]> = smallvec![0u32; num_new_tasks];
26 self.time.extend_from_slice(&clock);
27 }
28
29 pub fn increment(&mut self, task_id: TaskId) {
30 self.time[task_id.0] += 1;
31 }
32
33 pub fn update(&mut self, other: &Self) {
35 let n1 = self.time.len();
36 let n2 = other.time.len();
37 for i in 0..n1.min(n2) {
38 self.time[i] = self.time[i].max(other.time[i])
39 }
40 for i in n1..n2 {
41 self.time.push(other.time[i]);
43 }
44 }
45
46 pub fn get(&self, i: usize) -> u32 {
47 self.time[i]
48 }
49 }
50
51 impl<const N: usize> From<&[u32; N]> for VectorClock {
52 fn from(v: &[u32; N]) -> Self {
53 Self {
54 time: SmallVec::from(&v[..]),
55 }
56 }
57 }
58
59 impl From<&[u32]> for VectorClock {
60 fn from(v: &[u32]) -> Self {
61 Self {
62 time: SmallVec::from(v),
63 }
64 }
65 }
66
67 impl std::ops::Deref for VectorClock {
68 type Target = [u32];
69 fn deref(&self) -> &Self::Target {
70 &self.time[..]
71 }
72 }
73
74 fn unify(a: Ordering, b: Ordering) -> Option<Ordering> {
75 use Ordering::*;
76
77 match (a, b) {
78 (Equal, Equal) => Some(Equal),
79 (Less, Greater) | (Greater, Less) => None,
80 (Less, _) | (_, Less) => Some(Less),
81 (Greater, _) | (_, Greater) => Some(Greater),
82 }
83 }
84
85 impl PartialOrd for VectorClock {
86 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
88 let n1 = self.time.len();
89 let n2 = other.time.len();
90 let mut ord = n1.cmp(&n2);
92 for i in 0..n1.min(n2) {
93 ord = unify(ord, self.time[i].cmp(&other.time[i]))?; }
95 Some(ord)
96 }
97 }
98}
99
100#[cfg(any(not(any(test, feature = "vector-clocks")), feature = "bench-no-vector-clocks"))]
103mod vector_clock {
104 use super::*;
105
106 #[derive(Clone, Debug, PartialEq, Eq)]
107 pub struct VectorClock;
108
109 impl VectorClock {
110 pub const fn new() -> Self {
111 Self
112 }
113
114 pub fn extend(&mut self, _task_id: TaskId) {
115 }
117
118 pub fn increment(&mut self, _task_id: TaskId) {
119 }
121
122 pub fn update(&mut self, _other: &Self) {
123 }
125
126 pub fn get(&self, _i: usize) -> u32 {
127 0
128 }
129 }
130
131 impl<const N: usize> From<&[u32; N]> for VectorClock {
132 fn from(_v: &[u32; N]) -> Self {
133 Self
134 }
135 }
136
137 impl From<&[u32]> for VectorClock {
138 fn from(_v: &[u32]) -> Self {
139 Self
140 }
141 }
142
143 impl std::ops::Deref for VectorClock {
144 type Target = [u32];
145 fn deref(&self) -> &Self::Target {
146 &[]
147 }
148 }
149
150 impl PartialOrd for VectorClock {
151 fn partial_cmp(&self, _other: &Self) -> Option<Ordering> {
152 Some(Ordering::Equal)
153 }
154 }
155}
156
157pub use vector_clock::VectorClock;
158
159#[cfg(test)]
160mod test {
161 use super::*;
162
163 #[test]
164 fn vector_clock() {
165 let v1 = VectorClock::from(&[1, 2, 3, 4]);
166 let v2 = VectorClock::from(&[1, 2, 4, 5]);
167 let v3 = VectorClock::from(&[1, 2, 3, 1]);
168 let v4 = VectorClock::from(&[1, 2, 4, 1]);
169 let v5 = VectorClock::from(&[1, 2, 3, 4]);
170 assert!(v1 < v2 && v1 > v3 && v1 == v5);
171 assert!(v2 > v3 && v2 > v4);
172 assert!(v3 < v4);
173 assert_eq!(v1.partial_cmp(&v4), None);
174
175 let v1 = VectorClock::from(&[1, 2, 3, 4]);
176 let v2 = VectorClock::from(&[1, 2, 2]);
177 let v3 = VectorClock::from(&[1, 2, 3]);
178 let v4 = VectorClock::from(&[1, 2, 4]);
179 assert!(v1 > v2);
180 assert!(v1 > v3);
181 assert_eq!(v1.partial_cmp(&v4), None);
182
183 let v1 = VectorClock::from(&[]);
184 let v2 = VectorClock::from(&[1]);
185 assert!(v1 < v2);
186
187 let v1 = VectorClock::from(&[1, 2, 1]);
188 let v2 = VectorClock::from(&[1, 3]);
189 let v3 = VectorClock::from(&[1, 1, 1, 2]);
190 let v4 = VectorClock::from(&[1, 1, 2]);
191
192 let mut v = v1.clone();
193 v.update(&v2);
194 assert_eq!(v, VectorClock::from(&[1, 3, 1]));
195
196 let mut v = v1.clone();
197 v.update(&v3);
198 assert_eq!(v, VectorClock::from(&[1, 2, 1, 2]));
199
200 let mut v = v1.clone();
201 v.update(&v4);
202 assert_eq!(v, VectorClock::from(&[1, 2, 2]));
203
204 let mut v = v1.clone();
205 v.update(&VectorClock::new());
206 assert_eq!(v, v1);
207 }
208}