1use std::cmp::Ordering;
2use std::fmt::Debug;
3use std::ops::{Index, Shr};
4
5use rustc_index::Idx;
6use rustc_span::{DUMMY_SP, Span, SpanData};
7use smallvec::SmallVec;
8
9use super::data_race::NaReadType;
10
11#[derive(Clone, Copy, Debug, PartialOrd, Ord, PartialEq, Eq, Hash)]
15pub(super) struct VectorIdx(u32);
16
17impl VectorIdx {
18 #[inline(always)]
19 fn to_u32(self) -> u32 {
20 self.0
21 }
22}
23
24impl Idx for VectorIdx {
25 #[inline]
26 fn new(idx: usize) -> Self {
27 VectorIdx(u32::try_from(idx).unwrap())
28 }
29
30 #[inline]
31 fn index(self) -> usize {
32 usize::try_from(self.0).unwrap()
33 }
34}
35
36impl From<u32> for VectorIdx {
37 #[inline]
38 fn from(id: u32) -> Self {
39 Self(id)
40 }
41}
42
43const SMALL_VECTOR: usize = 4;
46
47#[derive(Clone, Copy, Debug)]
51pub(super) struct VTimestamp {
52 time_and_read_type: u32,
55 pub span: Span,
56}
57
58impl VTimestamp {
59 pub const ZERO: VTimestamp = VTimestamp::new(0, NaReadType::Read, DUMMY_SP);
60
61 #[inline]
62 const fn encode_time_and_read_type(time: u32, read_type: NaReadType) -> u32 {
63 let read_type_bit = match read_type {
64 NaReadType::Read => 0,
65 NaReadType::Retag => 1,
66 };
67 read_type_bit | time.checked_mul(2).expect("Vector clock overflow")
69 }
70
71 #[inline]
72 const fn new(time: u32, read_type: NaReadType, span: Span) -> Self {
73 Self { time_and_read_type: Self::encode_time_and_read_type(time, read_type), span }
74 }
75
76 #[inline]
77 fn time(&self) -> u32 {
78 self.time_and_read_type.shr(1)
79 }
80
81 #[inline]
82 fn set_time(&mut self, time: u32) {
83 self.time_and_read_type = Self::encode_time_and_read_type(time, self.read_type());
84 }
85
86 #[inline]
87 pub(super) fn read_type(&self) -> NaReadType {
88 if self.time_and_read_type & 1 == 0 { NaReadType::Read } else { NaReadType::Retag }
89 }
90
91 #[inline]
92 pub(super) fn set_read_type(&mut self, read_type: NaReadType) {
93 self.time_and_read_type = Self::encode_time_and_read_type(self.time(), read_type);
94 }
95
96 #[inline]
97 pub(super) fn span_data(&self) -> SpanData {
98 self.span.data()
99 }
100}
101
102impl PartialEq for VTimestamp {
103 fn eq(&self, other: &Self) -> bool {
104 self.time() == other.time()
105 }
106}
107
108impl Eq for VTimestamp {}
109
110impl PartialOrd for VTimestamp {
111 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
112 Some(self.cmp(other))
113 }
114}
115
116impl Ord for VTimestamp {
117 fn cmp(&self, other: &Self) -> Ordering {
118 self.time().cmp(&other.time())
119 }
120}
121
122#[derive(PartialEq, Eq, Default, Debug)]
136pub struct VClock(SmallVec<[VTimestamp; SMALL_VECTOR]>);
137
138impl VClock {
139 pub(super) fn new_with_index(index: VectorIdx, timestamp: VTimestamp) -> VClock {
142 if timestamp.time() == 0 {
143 return VClock::default();
144 }
145 let len = index.index() + 1;
146 let mut vec = smallvec::smallvec![VTimestamp::ZERO; len];
147 vec[index.index()] = timestamp;
148 VClock(vec)
149 }
150
151 #[inline]
153 pub(super) fn as_slice(&self) -> &[VTimestamp] {
154 debug_assert!(self.0.last().is_none_or(|t| t.time() != 0));
155 self.0.as_slice()
156 }
157
158 #[inline]
159 pub(super) fn index_mut(&mut self, index: VectorIdx) -> &mut VTimestamp {
160 self.0.as_mut_slice().get_mut(index.to_u32() as usize).unwrap()
161 }
162
163 #[inline]
167 fn get_mut_with_min_len(&mut self, min_len: usize) -> &mut [VTimestamp] {
168 if self.0.len() < min_len {
169 self.0.resize(min_len, VTimestamp::ZERO);
170 }
171 assert!(self.0.len() >= min_len);
172 self.0.as_mut_slice()
173 }
174
175 #[inline]
178 pub(super) fn increment_index(&mut self, idx: VectorIdx, current_span: Span) {
179 let idx = idx.index();
180 let mut_slice = self.get_mut_with_min_len(idx + 1);
181 let idx_ref = &mut mut_slice[idx];
182 idx_ref.set_time(idx_ref.time().checked_add(1).expect("Vector clock overflow"));
183 if !current_span.is_dummy() {
184 idx_ref.span = current_span;
185 }
186 }
187
188 pub fn join(&mut self, other: &Self) {
192 let rhs_slice = other.as_slice();
193 let lhs_slice = self.get_mut_with_min_len(rhs_slice.len());
194 for (l, &r) in lhs_slice.iter_mut().zip(rhs_slice.iter()) {
195 let l_span = l.span;
196 let r_span = r.span;
197 *l = r.max(*l);
198 l.span = l.span.substitute_dummy(r_span).substitute_dummy(l_span);
199 }
200 }
201
202 pub(super) fn set_at_index(&mut self, other: &Self, idx: VectorIdx) {
204 let new_timestamp = other[idx];
205 if new_timestamp.time() == 0 {
207 if idx.index() >= self.0.len() {
208 return;
210 }
211 }
214
215 let mut_slice = self.get_mut_with_min_len(idx.index() + 1);
216 let mut_timestamp = &mut mut_slice[idx.index()];
217
218 let prev_span = mut_timestamp.span;
219
220 assert!(*mut_timestamp <= new_timestamp, "set_at_index: may only increase the timestamp");
221 *mut_timestamp = new_timestamp;
222
223 let span = &mut mut_timestamp.span;
224 *span = span.substitute_dummy(prev_span);
225 }
226
227 #[inline]
229 pub(super) fn set_zero_vector(&mut self) {
230 self.0.clear();
231 }
232}
233
234impl Clone for VClock {
235 fn clone(&self) -> Self {
236 VClock(self.0.clone())
237 }
238
239 fn clone_from(&mut self, source: &Self) {
244 let source_slice = source.as_slice();
245 self.0.clear();
246 self.0.extend_from_slice(source_slice);
247 }
248}
249
250impl PartialOrd for VClock {
251 fn partial_cmp(&self, other: &VClock) -> Option<Ordering> {
252 let lhs_slice = self.as_slice();
254 let rhs_slice = other.as_slice();
255
256 let mut iter = lhs_slice.iter().zip(rhs_slice.iter());
265 let mut order = match iter.next() {
266 Some((lhs, rhs)) => lhs.cmp(rhs),
267 None => Ordering::Equal,
268 };
269 for (l, r) in iter {
270 match order {
271 Ordering::Equal => order = l.cmp(r),
272 Ordering::Less =>
273 if l > r {
274 return None;
275 },
276 Ordering::Greater =>
277 if l < r {
278 return None;
279 },
280 }
281 }
282
283 let l_len = lhs_slice.len();
288 let r_len = rhs_slice.len();
289 match l_len.cmp(&r_len) {
290 Ordering::Equal => Some(order),
292 Ordering::Less =>
295 match order {
296 Ordering::Less | Ordering::Equal => Some(Ordering::Less),
297 Ordering::Greater => None,
298 },
299 Ordering::Greater =>
302 match order {
303 Ordering::Greater | Ordering::Equal => Some(Ordering::Greater),
304 Ordering::Less => None,
305 },
306 }
307 }
308
309 fn lt(&self, other: &VClock) -> bool {
310 let lhs_slice = self.as_slice();
312 let rhs_slice = other.as_slice();
313
314 let l_len = lhs_slice.len();
319 let r_len = rhs_slice.len();
320 if l_len <= r_len {
321 let mut equal = l_len == r_len;
328 for (&l, &r) in lhs_slice.iter().zip(rhs_slice.iter()) {
329 if l > r {
330 return false;
331 } else if l < r {
332 equal = false;
333 }
334 }
335 !equal
336 } else {
337 false
338 }
339 }
340
341 fn le(&self, other: &VClock) -> bool {
342 let lhs_slice = self.as_slice();
344 let rhs_slice = other.as_slice();
345
346 let l_len = lhs_slice.len();
351 let r_len = rhs_slice.len();
352 if l_len <= r_len {
353 !lhs_slice.iter().zip(rhs_slice.iter()).any(|(&l, &r)| l > r)
358 } else {
359 false
360 }
361 }
362
363 fn gt(&self, other: &VClock) -> bool {
364 let lhs_slice = self.as_slice();
366 let rhs_slice = other.as_slice();
367
368 let l_len = lhs_slice.len();
373 let r_len = rhs_slice.len();
374 if l_len >= r_len {
375 let mut equal = l_len == r_len;
382 for (&l, &r) in lhs_slice.iter().zip(rhs_slice.iter()) {
383 if l < r {
384 return false;
385 } else if l > r {
386 equal = false;
387 }
388 }
389 !equal
390 } else {
391 false
392 }
393 }
394
395 fn ge(&self, other: &VClock) -> bool {
396 let lhs_slice = self.as_slice();
398 let rhs_slice = other.as_slice();
399
400 let l_len = lhs_slice.len();
405 let r_len = rhs_slice.len();
406 if l_len >= r_len {
407 !lhs_slice.iter().zip(rhs_slice.iter()).any(|(&l, &r)| l < r)
412 } else {
413 false
414 }
415 }
416}
417
418impl Index<VectorIdx> for VClock {
419 type Output = VTimestamp;
420
421 #[inline]
422 fn index(&self, index: VectorIdx) -> &VTimestamp {
423 self.as_slice().get(index.to_u32() as usize).unwrap_or(&VTimestamp::ZERO)
424 }
425}
426
427#[cfg(test)]
431mod tests {
432 use std::cmp::Ordering;
433
434 use rustc_span::DUMMY_SP;
435
436 use super::{VClock, VTimestamp, VectorIdx};
437 use crate::concurrency::data_race::NaReadType;
438
439 #[test]
440 fn test_equal() {
441 let mut c1 = VClock::default();
442 let mut c2 = VClock::default();
443 assert_eq!(c1, c2);
444 c1.increment_index(VectorIdx(5), DUMMY_SP);
445 assert_ne!(c1, c2);
446 c2.increment_index(VectorIdx(53), DUMMY_SP);
447 assert_ne!(c1, c2);
448 c1.increment_index(VectorIdx(53), DUMMY_SP);
449 assert_ne!(c1, c2);
450 c2.increment_index(VectorIdx(5), DUMMY_SP);
451 assert_eq!(c1, c2);
452 }
453
454 #[test]
455 fn test_partial_order() {
456 assert_order(&[1], &[1], Some(Ordering::Equal));
458 assert_order(&[1], &[2], Some(Ordering::Less));
459 assert_order(&[2], &[1], Some(Ordering::Greater));
460 assert_order(&[1], &[1, 2], Some(Ordering::Less));
461 assert_order(&[2], &[1, 2], None);
462
463 assert_order(&[400], &[0, 1], None);
465
466 assert_order(
468 &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
469 &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 0, 0],
470 Some(Ordering::Equal),
471 );
472 assert_order(
473 &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
474 &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 1, 0],
475 Some(Ordering::Less),
476 );
477 assert_order(
478 &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11],
479 &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 0, 0],
480 Some(Ordering::Greater),
481 );
482 assert_order(
483 &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11],
484 &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 1, 0],
485 None,
486 );
487 assert_order(
488 &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9],
489 &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 0, 0],
490 Some(Ordering::Less),
491 );
492 assert_order(
493 &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9],
494 &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 1, 0],
495 Some(Ordering::Less),
496 );
497 }
498
499 fn from_slice(mut slice: &[u32]) -> VClock {
500 while let Some(0) = slice.last() {
501 slice = &slice[..slice.len() - 1]
502 }
503 VClock(
504 slice
505 .iter()
506 .copied()
507 .map(|time| VTimestamp::new(time, NaReadType::Read, DUMMY_SP))
508 .collect(),
509 )
510 }
511
512 fn assert_order(l: &[u32], r: &[u32], o: Option<Ordering>) {
513 let l = from_slice(l);
514 let r = from_slice(r);
515
516 let compare = l.partial_cmp(&r);
518 assert_eq!(compare, o, "Invalid comparison\n l: {l:?}\n r: {r:?}");
519 let alt_compare = r.partial_cmp(&l);
520 assert_eq!(
521 alt_compare,
522 o.map(Ordering::reverse),
523 "Invalid alt comparison\n l: {l:?}\n r: {r:?}"
524 );
525
526 assert_eq!(
528 matches!(compare, Some(Ordering::Less)),
529 l < r,
530 "Invalid (<):\n l: {l:?}\n r: {r:?}"
531 );
532 assert_eq!(
533 matches!(compare, Some(Ordering::Less) | Some(Ordering::Equal)),
534 l <= r,
535 "Invalid (<=):\n l: {l:?}\n r: {r:?}"
536 );
537 assert_eq!(
538 matches!(compare, Some(Ordering::Greater)),
539 l > r,
540 "Invalid (>):\n l: {l:?}\n r: {r:?}"
541 );
542 assert_eq!(
543 matches!(compare, Some(Ordering::Greater) | Some(Ordering::Equal)),
544 l >= r,
545 "Invalid (>=):\n l: {l:?}\n r: {r:?}"
546 );
547 assert_eq!(
548 matches!(alt_compare, Some(Ordering::Less)),
549 r < l,
550 "Invalid alt (<):\n l: {l:?}\n r: {r:?}"
551 );
552 assert_eq!(
553 matches!(alt_compare, Some(Ordering::Less) | Some(Ordering::Equal)),
554 r <= l,
555 "Invalid alt (<=):\n l: {l:?}\n r: {r:?}"
556 );
557 assert_eq!(
558 matches!(alt_compare, Some(Ordering::Greater)),
559 r > l,
560 "Invalid alt (>):\n l: {l:?}\n r: {r:?}"
561 );
562 assert_eq!(
563 matches!(alt_compare, Some(Ordering::Greater) | Some(Ordering::Equal)),
564 r >= l,
565 "Invalid alt (>=):\n l: {l:?}\n r: {r:?}"
566 );
567 }
568
569 #[test]
570 fn set_index_to_0() {
571 let mut clock1 = from_slice(&[0, 1, 2, 3]);
572 let clock2 = from_slice(&[0, 2, 3, 4, 0, 5]);
573 clock1.set_at_index(&clock2, VectorIdx(4));
576 assert!(clock1.0.last().unwrap().time() != 0);
578 }
579}