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;
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 #[inline]
108 pub(super) fn span_data(&self) -> SpanData {
109 self.span.data()
110 }
111}
112
113impl PartialEq for VTimestamp {
114 fn eq(&self, other: &Self) -> bool {
115 self.time() == other.time()
116 }
117}
118
119impl Eq for VTimestamp {}
120
121impl PartialOrd for VTimestamp {
122 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
123 Some(self.cmp(other))
124 }
125}
126
127impl Ord for VTimestamp {
128 fn cmp(&self, other: &Self) -> Ordering {
129 self.time().cmp(&other.time())
130 }
131}
132
133#[derive(PartialEq, Eq, Default, Debug)]
147pub struct VClock(SmallVec<[VTimestamp; SMALL_VECTOR]>);
148
149impl VClock {
150 pub(super) fn new_with_index(index: VectorIdx, timestamp: VTimestamp) -> VClock {
153 if timestamp.time() == 0 {
154 return VClock::default();
155 }
156 let len = index.index() + 1;
157 let mut vec = smallvec::smallvec![VTimestamp::ZERO; len];
158 vec[index.index()] = timestamp;
159 VClock(vec)
160 }
161
162 #[inline]
164 pub(super) fn as_slice(&self) -> &[VTimestamp] {
165 debug_assert!(self.0.last().is_none_or(|t| t.time() != 0));
166 self.0.as_slice()
167 }
168
169 #[inline]
170 pub(super) fn index_mut(&mut self, index: VectorIdx) -> &mut VTimestamp {
171 self.0.as_mut_slice().get_mut(index.to_u32().to_usize()).unwrap()
172 }
173
174 #[inline]
178 fn get_mut_with_min_len(&mut self, min_len: usize) -> &mut [VTimestamp] {
179 if self.0.len() < min_len {
180 self.0.resize(min_len, VTimestamp::ZERO);
181 }
182 assert!(self.0.len() >= min_len);
183 self.0.as_mut_slice()
184 }
185
186 #[inline]
189 pub(super) fn increment_index(&mut self, idx: VectorIdx, current_span: Span) {
190 let idx = idx.index();
191 let mut_slice = self.get_mut_with_min_len(idx + 1);
192 let idx_ref = &mut mut_slice[idx];
193 idx_ref.set_time(idx_ref.time().checked_add(1).expect("Vector clock overflow"));
194 if !current_span.is_dummy() {
195 idx_ref.span = current_span;
196 }
197 }
198
199 pub fn join(&mut self, other: &Self) {
203 let rhs_slice = other.as_slice();
204 let lhs_slice = self.get_mut_with_min_len(rhs_slice.len());
205 for (l, &r) in lhs_slice.iter_mut().zip(rhs_slice.iter()) {
206 let l_span = l.span;
207 let r_span = r.span;
208 *l = r.max(*l);
209 l.span = l.span.substitute_dummy(r_span).substitute_dummy(l_span);
210 }
211 }
212
213 pub(super) fn set_at_index(&mut self, other: &Self, idx: VectorIdx) {
215 let new_timestamp = other[idx];
216 if new_timestamp.time() == 0 {
218 if idx.index() >= self.0.len() {
219 return;
221 }
222 }
225
226 let mut_slice = self.get_mut_with_min_len(idx.index() + 1);
227 let mut_timestamp = &mut mut_slice[idx.index()];
228
229 let prev_span = mut_timestamp.span;
230
231 assert!(*mut_timestamp <= new_timestamp, "set_at_index: may only increase the timestamp");
232 *mut_timestamp = new_timestamp;
233
234 let span = &mut mut_timestamp.span;
235 *span = span.substitute_dummy(prev_span);
236 }
237
238 #[inline]
240 pub(super) fn set_zero_vector(&mut self) {
241 self.0.clear();
242 }
243}
244
245impl Clone for VClock {
246 fn clone(&self) -> Self {
247 VClock(self.0.clone())
248 }
249
250 fn clone_from(&mut self, source: &Self) {
255 let source_slice = source.as_slice();
256 self.0.clear();
257 self.0.extend_from_slice(source_slice);
258 }
259}
260
261impl PartialOrd for VClock {
262 fn partial_cmp(&self, other: &VClock) -> Option<Ordering> {
263 let lhs_slice = self.as_slice();
265 let rhs_slice = other.as_slice();
266
267 let mut iter = lhs_slice.iter().zip(rhs_slice.iter());
276 let mut order = match iter.next() {
277 Some((lhs, rhs)) => lhs.cmp(rhs),
278 None => Ordering::Equal,
279 };
280 for (l, r) in iter {
281 match order {
282 Ordering::Equal => order = l.cmp(r),
283 Ordering::Less =>
284 if l > r {
285 return None;
286 },
287 Ordering::Greater =>
288 if l < r {
289 return None;
290 },
291 }
292 }
293
294 let l_len = lhs_slice.len();
299 let r_len = rhs_slice.len();
300 match l_len.cmp(&r_len) {
301 Ordering::Equal => Some(order),
303 Ordering::Less =>
306 match order {
307 Ordering::Less | Ordering::Equal => Some(Ordering::Less),
308 Ordering::Greater => None,
309 },
310 Ordering::Greater =>
313 match order {
314 Ordering::Greater | Ordering::Equal => Some(Ordering::Greater),
315 Ordering::Less => None,
316 },
317 }
318 }
319
320 fn lt(&self, other: &VClock) -> bool {
321 let lhs_slice = self.as_slice();
323 let rhs_slice = other.as_slice();
324
325 let l_len = lhs_slice.len();
330 let r_len = rhs_slice.len();
331 if l_len <= r_len {
332 let mut equal = l_len == r_len;
339 for (&l, &r) in lhs_slice.iter().zip(rhs_slice.iter()) {
340 if l > r {
341 return false;
342 } else if l < r {
343 equal = false;
344 }
345 }
346 !equal
347 } else {
348 false
349 }
350 }
351
352 fn le(&self, other: &VClock) -> bool {
353 let lhs_slice = self.as_slice();
355 let rhs_slice = other.as_slice();
356
357 let l_len = lhs_slice.len();
362 let r_len = rhs_slice.len();
363 if l_len <= r_len {
364 !lhs_slice.iter().zip(rhs_slice.iter()).any(|(&l, &r)| l > r)
369 } else {
370 false
371 }
372 }
373
374 fn gt(&self, other: &VClock) -> bool {
375 let lhs_slice = self.as_slice();
377 let rhs_slice = other.as_slice();
378
379 let l_len = lhs_slice.len();
384 let r_len = rhs_slice.len();
385 if l_len >= r_len {
386 let mut equal = l_len == r_len;
393 for (&l, &r) in lhs_slice.iter().zip(rhs_slice.iter()) {
394 if l < r {
395 return false;
396 } else if l > r {
397 equal = false;
398 }
399 }
400 !equal
401 } else {
402 false
403 }
404 }
405
406 fn ge(&self, other: &VClock) -> bool {
407 let lhs_slice = self.as_slice();
409 let rhs_slice = other.as_slice();
410
411 let l_len = lhs_slice.len();
416 let r_len = rhs_slice.len();
417 if l_len >= r_len {
418 !lhs_slice.iter().zip(rhs_slice.iter()).any(|(&l, &r)| l < r)
423 } else {
424 false
425 }
426 }
427}
428
429impl Index<VectorIdx> for VClock {
430 type Output = VTimestamp;
431
432 #[inline]
433 fn index(&self, index: VectorIdx) -> &VTimestamp {
434 self.as_slice().get(index.to_u32().to_usize()).unwrap_or(&VTimestamp::ZERO)
435 }
436}
437
438#[cfg(test)]
442mod tests {
443 use std::cmp::Ordering;
444
445 use rustc_span::DUMMY_SP;
446
447 use super::{VClock, VTimestamp, VectorIdx};
448 use crate::concurrency::data_race::NaReadType;
449
450 #[test]
451 fn test_equal() {
452 let mut c1 = VClock::default();
453 let mut c2 = VClock::default();
454 assert_eq!(c1, c2);
455 c1.increment_index(VectorIdx(5), DUMMY_SP);
456 assert_ne!(c1, c2);
457 c2.increment_index(VectorIdx(53), DUMMY_SP);
458 assert_ne!(c1, c2);
459 c1.increment_index(VectorIdx(53), DUMMY_SP);
460 assert_ne!(c1, c2);
461 c2.increment_index(VectorIdx(5), DUMMY_SP);
462 assert_eq!(c1, c2);
463 }
464
465 #[test]
466 fn test_partial_order() {
467 assert_order(&[1], &[1], Some(Ordering::Equal));
469 assert_order(&[1], &[2], Some(Ordering::Less));
470 assert_order(&[2], &[1], Some(Ordering::Greater));
471 assert_order(&[1], &[1, 2], Some(Ordering::Less));
472 assert_order(&[2], &[1, 2], None);
473
474 assert_order(&[400], &[0, 1], None);
476
477 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, 0, 0],
481 Some(Ordering::Equal),
482 );
483 assert_order(
484 &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
485 &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 1, 0],
486 Some(Ordering::Less),
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, 0, 0],
491 Some(Ordering::Greater),
492 );
493 assert_order(
494 &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11],
495 &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 1, 0],
496 None,
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, 0, 0],
501 Some(Ordering::Less),
502 );
503 assert_order(
504 &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9],
505 &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 1, 0],
506 Some(Ordering::Less),
507 );
508 }
509
510 fn from_slice(mut slice: &[u32]) -> VClock {
511 while let Some(0) = slice.last() {
512 slice = &slice[..slice.len() - 1]
513 }
514 VClock(
515 slice
516 .iter()
517 .copied()
518 .map(|time| VTimestamp::new(time, NaReadType::Read, DUMMY_SP))
519 .collect(),
520 )
521 }
522
523 fn assert_order(l: &[u32], r: &[u32], o: Option<Ordering>) {
524 let l = from_slice(l);
525 let r = from_slice(r);
526
527 let compare = l.partial_cmp(&r);
529 assert_eq!(compare, o, "Invalid comparison\n l: {l:?}\n r: {r:?}");
530 let alt_compare = r.partial_cmp(&l);
531 assert_eq!(
532 alt_compare,
533 o.map(Ordering::reverse),
534 "Invalid alt comparison\n l: {l:?}\n r: {r:?}"
535 );
536
537 assert_eq!(
539 matches!(compare, Some(Ordering::Less)),
540 l < r,
541 "Invalid (<):\n l: {l:?}\n r: {r:?}"
542 );
543 assert_eq!(
544 matches!(compare, Some(Ordering::Less) | Some(Ordering::Equal)),
545 l <= r,
546 "Invalid (<=):\n l: {l:?}\n r: {r:?}"
547 );
548 assert_eq!(
549 matches!(compare, Some(Ordering::Greater)),
550 l > r,
551 "Invalid (>):\n l: {l:?}\n r: {r:?}"
552 );
553 assert_eq!(
554 matches!(compare, Some(Ordering::Greater) | Some(Ordering::Equal)),
555 l >= r,
556 "Invalid (>=):\n l: {l:?}\n r: {r:?}"
557 );
558 assert_eq!(
559 matches!(alt_compare, Some(Ordering::Less)),
560 r < l,
561 "Invalid alt (<):\n l: {l:?}\n r: {r:?}"
562 );
563 assert_eq!(
564 matches!(alt_compare, Some(Ordering::Less) | Some(Ordering::Equal)),
565 r <= l,
566 "Invalid alt (<=):\n l: {l:?}\n r: {r:?}"
567 );
568 assert_eq!(
569 matches!(alt_compare, Some(Ordering::Greater)),
570 r > l,
571 "Invalid alt (>):\n l: {l:?}\n r: {r:?}"
572 );
573 assert_eq!(
574 matches!(alt_compare, Some(Ordering::Greater) | Some(Ordering::Equal)),
575 r >= l,
576 "Invalid alt (>=):\n l: {l:?}\n r: {r:?}"
577 );
578 }
579
580 #[test]
581 fn set_index_to_0() {
582 let mut clock1 = from_slice(&[0, 1, 2, 3]);
583 let clock2 = from_slice(&[0, 2, 3, 4, 0, 5]);
584 clock1.set_at_index(&clock2, VectorIdx(4));
587 assert!(clock1.0.last().unwrap().time() != 0);
589 }
590}