1use std::cmp::Ordering;
2use std::fmt::Debug;
3use std::ops::{Index, Shr};
4
5use rustc_index::Idx;
6use rustc_span::{DUMMY_SP, Span};
7use smallvec::SmallVec;
8
9use super::data_race::NaReadType;
10use crate::helpers::ToUsize;
11
12#[derive(Clone, Copy, Debug, PartialOrd, Ord, PartialEq, Eq, Hash)]
16pub(super) struct VectorIdx(u32);
17
18impl VectorIdx {
19 #[inline(always)]
20 fn to_u32(self) -> u32 {
21 self.0
22 }
23}
24
25impl Idx for VectorIdx {
26 #[inline]
27 fn new(idx: usize) -> Self {
28 VectorIdx(u32::try_from(idx).unwrap())
29 }
30
31 #[inline]
32 fn index(self) -> usize {
33 usize::try_from(self.0).unwrap()
34 }
35}
36
37impl From<u32> for VectorIdx {
38 #[inline]
39 fn from(id: u32) -> Self {
40 Self(id)
41 }
42}
43
44const SMALL_VECTOR: usize = 4;
47
48#[derive(Clone, Copy)]
52pub(super) struct VTimestamp {
53 time_and_read_type: u32,
56 pub span: Span,
57}
58
59impl Debug for VTimestamp {
60 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
61 f.debug_struct("VTimestamp")
62 .field("time", &self.time())
63 .field("read_type", &self.read_type())
64 .field("span", &self.span)
65 .finish()
66 }
67}
68
69impl VTimestamp {
70 pub const ZERO: VTimestamp = VTimestamp::new(0, NaReadType::Read, DUMMY_SP);
71
72 #[inline]
73 const fn encode_time_and_read_type(time: u32, read_type: NaReadType) -> u32 {
74 let read_type_bit = match read_type {
75 NaReadType::Read => 0,
76 NaReadType::Retag => 1,
77 };
78 read_type_bit | time.checked_mul(2).expect("Vector clock overflow")
80 }
81
82 #[inline]
83 const fn new(time: u32, read_type: NaReadType, span: Span) -> Self {
84 Self { time_and_read_type: Self::encode_time_and_read_type(time, read_type), span }
85 }
86
87 #[inline]
88 fn time(&self) -> u32 {
89 self.time_and_read_type.shr(1)
90 }
91
92 #[inline]
93 fn set_time(&mut self, time: u32) {
94 self.time_and_read_type = Self::encode_time_and_read_type(time, self.read_type());
95 }
96
97 #[inline]
98 pub(super) fn read_type(&self) -> NaReadType {
99 if self.time_and_read_type & 1 == 0 { NaReadType::Read } else { NaReadType::Retag }
100 }
101
102 #[inline]
103 pub(super) fn set_read_type(&mut self, read_type: NaReadType) {
104 self.time_and_read_type = Self::encode_time_and_read_type(self.time(), read_type);
105 }
106}
107
108impl PartialEq for VTimestamp {
109 fn eq(&self, other: &Self) -> bool {
110 self.time() == other.time()
111 }
112}
113
114impl Eq for VTimestamp {}
115
116impl PartialOrd for VTimestamp {
117 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
118 Some(self.cmp(other))
119 }
120}
121
122impl Ord for VTimestamp {
123 fn cmp(&self, other: &Self) -> Ordering {
124 self.time().cmp(&other.time())
125 }
126}
127
128#[derive(PartialEq, Eq, Default, Debug)]
142pub struct VClock(SmallVec<[VTimestamp; SMALL_VECTOR]>);
143
144impl VClock {
145 pub(super) fn new_with_index(index: VectorIdx, timestamp: VTimestamp) -> VClock {
148 if timestamp.time() == 0 {
149 return VClock::default();
150 }
151 let len = index.index() + 1;
152 let mut vec = smallvec::smallvec![VTimestamp::ZERO; len];
153 vec[index.index()] = timestamp;
154 VClock(vec)
155 }
156
157 #[inline]
159 pub(super) fn as_slice(&self) -> &[VTimestamp] {
160 debug_assert!(self.0.last().is_none_or(|t| t.time() != 0));
161 self.0.as_slice()
162 }
163
164 #[inline]
165 pub(super) fn index_mut(&mut self, index: VectorIdx) -> &mut VTimestamp {
166 self.0.as_mut_slice().get_mut(index.to_u32().to_usize()).unwrap()
167 }
168
169 #[inline]
173 fn get_mut_with_min_len(&mut self, min_len: usize) -> &mut [VTimestamp] {
174 if self.0.len() < min_len {
175 self.0.resize(min_len, VTimestamp::ZERO);
176 }
177 assert!(self.0.len() >= min_len);
178 self.0.as_mut_slice()
179 }
180
181 #[inline]
184 pub(super) fn increment_index(&mut self, idx: VectorIdx, current_span: Span) {
185 let idx = idx.index();
186 let mut_slice = self.get_mut_with_min_len(idx + 1);
187 let idx_ref = &mut mut_slice[idx];
188 idx_ref.set_time(idx_ref.time().checked_add(1).expect("Vector clock overflow"));
189 if !current_span.is_dummy() {
190 idx_ref.span = current_span;
191 }
192 }
193
194 pub fn join(&mut self, other: &Self) {
198 let rhs_slice = other.as_slice();
199 let lhs_slice = self.get_mut_with_min_len(rhs_slice.len());
200 for (l, &r) in lhs_slice.iter_mut().zip(rhs_slice.iter()) {
201 let l_span = l.span;
202 let r_span = r.span;
203 *l = r.max(*l);
204 l.span = l.span.substitute_dummy(r_span).substitute_dummy(l_span);
205 }
206 }
207
208 pub(super) fn set_at_index(&mut self, other: &Self, idx: VectorIdx) {
210 let new_timestamp = other[idx];
211 if new_timestamp.time() == 0 {
213 if idx.index() >= self.0.len() {
214 return;
216 }
217 }
220
221 let mut_slice = self.get_mut_with_min_len(idx.index() + 1);
222 let mut_timestamp = &mut mut_slice[idx.index()];
223
224 let prev_span = mut_timestamp.span;
225
226 assert!(*mut_timestamp <= new_timestamp, "set_at_index: may only increase the timestamp");
227 *mut_timestamp = new_timestamp;
228
229 let span = &mut mut_timestamp.span;
230 *span = span.substitute_dummy(prev_span);
231 }
232
233 #[inline]
235 pub(super) fn set_zero_vector(&mut self) {
236 self.0.clear();
237 }
238}
239
240impl Clone for VClock {
241 fn clone(&self) -> Self {
242 VClock(self.0.clone())
243 }
244
245 fn clone_from(&mut self, source: &Self) {
250 let source_slice = source.as_slice();
251 self.0.clear();
252 self.0.extend_from_slice(source_slice);
253 }
254}
255
256impl PartialOrd for VClock {
257 fn partial_cmp(&self, other: &VClock) -> Option<Ordering> {
258 let lhs_slice = self.as_slice();
260 let rhs_slice = other.as_slice();
261
262 let mut iter = lhs_slice.iter().zip(rhs_slice.iter());
271 let mut order = match iter.next() {
272 Some((lhs, rhs)) => lhs.cmp(rhs),
273 None => Ordering::Equal,
274 };
275 for (l, r) in iter {
276 match order {
277 Ordering::Equal => order = l.cmp(r),
278 Ordering::Less =>
279 if l > r {
280 return None;
281 },
282 Ordering::Greater =>
283 if l < r {
284 return None;
285 },
286 }
287 }
288
289 let l_len = lhs_slice.len();
294 let r_len = rhs_slice.len();
295 match l_len.cmp(&r_len) {
296 Ordering::Equal => Some(order),
298 Ordering::Less =>
301 match order {
302 Ordering::Less | Ordering::Equal => Some(Ordering::Less),
303 Ordering::Greater => None,
304 },
305 Ordering::Greater =>
308 match order {
309 Ordering::Greater | Ordering::Equal => Some(Ordering::Greater),
310 Ordering::Less => None,
311 },
312 }
313 }
314
315 fn lt(&self, other: &VClock) -> bool {
316 let lhs_slice = self.as_slice();
318 let rhs_slice = other.as_slice();
319
320 let l_len = lhs_slice.len();
325 let r_len = rhs_slice.len();
326 if l_len <= r_len {
327 let mut equal = l_len == r_len;
334 for (&l, &r) in lhs_slice.iter().zip(rhs_slice.iter()) {
335 if l > r {
336 return false;
337 } else if l < r {
338 equal = false;
339 }
340 }
341 !equal
342 } else {
343 false
344 }
345 }
346
347 fn le(&self, other: &VClock) -> bool {
348 let lhs_slice = self.as_slice();
350 let rhs_slice = other.as_slice();
351
352 let l_len = lhs_slice.len();
357 let r_len = rhs_slice.len();
358 if l_len <= r_len {
359 !lhs_slice.iter().zip(rhs_slice.iter()).any(|(&l, &r)| l > r)
364 } else {
365 false
366 }
367 }
368
369 fn gt(&self, other: &VClock) -> bool {
370 let lhs_slice = self.as_slice();
372 let rhs_slice = other.as_slice();
373
374 let l_len = lhs_slice.len();
379 let r_len = rhs_slice.len();
380 if l_len >= r_len {
381 let mut equal = l_len == r_len;
388 for (&l, &r) in lhs_slice.iter().zip(rhs_slice.iter()) {
389 if l < r {
390 return false;
391 } else if l > r {
392 equal = false;
393 }
394 }
395 !equal
396 } else {
397 false
398 }
399 }
400
401 fn ge(&self, other: &VClock) -> bool {
402 let lhs_slice = self.as_slice();
404 let rhs_slice = other.as_slice();
405
406 let l_len = lhs_slice.len();
411 let r_len = rhs_slice.len();
412 if l_len >= r_len {
413 !lhs_slice.iter().zip(rhs_slice.iter()).any(|(&l, &r)| l < r)
418 } else {
419 false
420 }
421 }
422}
423
424impl Index<VectorIdx> for VClock {
425 type Output = VTimestamp;
426
427 #[inline]
428 fn index(&self, index: VectorIdx) -> &VTimestamp {
429 self.as_slice().get(index.to_u32().to_usize()).unwrap_or(&VTimestamp::ZERO)
430 }
431}
432
433#[cfg(test)]
437mod tests {
438 use std::cmp::Ordering;
439
440 use rustc_span::DUMMY_SP;
441
442 use super::{VClock, VTimestamp, VectorIdx};
443 use crate::concurrency::data_race::NaReadType;
444
445 #[test]
446 fn test_equal() {
447 let mut c1 = VClock::default();
448 let mut c2 = VClock::default();
449 assert_eq!(c1, c2);
450 c1.increment_index(VectorIdx(5), DUMMY_SP);
451 assert_ne!(c1, c2);
452 c2.increment_index(VectorIdx(53), DUMMY_SP);
453 assert_ne!(c1, c2);
454 c1.increment_index(VectorIdx(53), DUMMY_SP);
455 assert_ne!(c1, c2);
456 c2.increment_index(VectorIdx(5), DUMMY_SP);
457 assert_eq!(c1, c2);
458 }
459
460 #[test]
461 fn test_partial_order() {
462 assert_order(&[1], &[1], Some(Ordering::Equal));
464 assert_order(&[1], &[2], Some(Ordering::Less));
465 assert_order(&[2], &[1], Some(Ordering::Greater));
466 assert_order(&[1], &[1, 2], Some(Ordering::Less));
467 assert_order(&[2], &[1, 2], None);
468
469 assert_order(&[400], &[0, 1], None);
471
472 assert_order(
474 &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
475 &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 0, 0],
476 Some(Ordering::Equal),
477 );
478 assert_order(
479 &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
480 &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 1, 0],
481 Some(Ordering::Less),
482 );
483 assert_order(
484 &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11],
485 &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 0, 0],
486 Some(Ordering::Greater),
487 );
488 assert_order(
489 &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11],
490 &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 1, 0],
491 None,
492 );
493 assert_order(
494 &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9],
495 &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 0, 0],
496 Some(Ordering::Less),
497 );
498 assert_order(
499 &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9],
500 &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 1, 0],
501 Some(Ordering::Less),
502 );
503 }
504
505 fn from_slice(mut slice: &[u32]) -> VClock {
506 while let Some(0) = slice.last() {
507 slice = &slice[..slice.len() - 1]
508 }
509 VClock(
510 slice
511 .iter()
512 .copied()
513 .map(|time| VTimestamp::new(time, NaReadType::Read, DUMMY_SP))
514 .collect(),
515 )
516 }
517
518 fn assert_order(l: &[u32], r: &[u32], o: Option<Ordering>) {
519 let l = from_slice(l);
520 let r = from_slice(r);
521
522 let compare = l.partial_cmp(&r);
524 assert_eq!(compare, o, "Invalid comparison\n l: {l:?}\n r: {r:?}");
525 let alt_compare = r.partial_cmp(&l);
526 assert_eq!(
527 alt_compare,
528 o.map(Ordering::reverse),
529 "Invalid alt comparison\n l: {l:?}\n r: {r:?}"
530 );
531
532 assert_eq!(
534 matches!(compare, Some(Ordering::Less)),
535 l < r,
536 "Invalid (<):\n l: {l:?}\n r: {r:?}"
537 );
538 assert_eq!(
539 matches!(compare, Some(Ordering::Less) | Some(Ordering::Equal)),
540 l <= r,
541 "Invalid (<=):\n l: {l:?}\n r: {r:?}"
542 );
543 assert_eq!(
544 matches!(compare, Some(Ordering::Greater)),
545 l > r,
546 "Invalid (>):\n l: {l:?}\n r: {r:?}"
547 );
548 assert_eq!(
549 matches!(compare, Some(Ordering::Greater) | Some(Ordering::Equal)),
550 l >= r,
551 "Invalid (>=):\n l: {l:?}\n r: {r:?}"
552 );
553 assert_eq!(
554 matches!(alt_compare, Some(Ordering::Less)),
555 r < l,
556 "Invalid alt (<):\n l: {l:?}\n r: {r:?}"
557 );
558 assert_eq!(
559 matches!(alt_compare, Some(Ordering::Less) | Some(Ordering::Equal)),
560 r <= l,
561 "Invalid alt (<=):\n l: {l:?}\n r: {r:?}"
562 );
563 assert_eq!(
564 matches!(alt_compare, Some(Ordering::Greater)),
565 r > l,
566 "Invalid alt (>):\n l: {l:?}\n r: {r:?}"
567 );
568 assert_eq!(
569 matches!(alt_compare, Some(Ordering::Greater) | Some(Ordering::Equal)),
570 r >= l,
571 "Invalid alt (>=):\n l: {l:?}\n r: {r:?}"
572 );
573 }
574
575 #[test]
576 fn set_index_to_0() {
577 let mut clock1 = from_slice(&[0, 1, 2, 3]);
578 let clock2 = from_slice(&[0, 2, 3, 4, 0, 5]);
579 clock1.set_at_index(&clock2, VectorIdx(4));
582 assert!(clock1.0.last().unwrap().time() != 0);
584 }
585}