Skip to main content

raphtory_core/entities/graph/
timer.rs

1use serde::{Deserialize, Serialize};
2use std::sync::atomic::{AtomicI64, Ordering};
3
4pub trait TimeCounterTrait {
5    fn cmp(a: i64, b: i64) -> bool;
6    fn counter(&self) -> &AtomicI64;
7
8    fn update(&self, new_value: i64) {
9        let mut current_value = self.get();
10        while Self::cmp(new_value, current_value) {
11            match self.counter().compare_exchange_weak(
12                current_value,
13                new_value,
14                Ordering::Relaxed,
15                Ordering::Relaxed,
16            ) {
17                Ok(_) => break,
18                Err(value) => current_value = value,
19            }
20        }
21    }
22    #[inline(always)]
23    fn get(&self) -> i64 {
24        self.counter().load(Ordering::Relaxed)
25    }
26}
27
28#[derive(Serialize, Deserialize, Debug)]
29pub struct MinCounter {
30    counter: AtomicI64,
31}
32
33impl Default for MinCounter {
34    fn default() -> Self {
35        Self::new()
36    }
37}
38
39impl From<i64> for MinCounter {
40    fn from(value: i64) -> Self {
41        let counter = AtomicI64::new(value);
42        Self { counter }
43    }
44}
45
46impl MinCounter {
47    pub fn new() -> Self {
48        Self {
49            counter: AtomicI64::new(i64::MAX),
50        }
51    }
52}
53
54impl TimeCounterTrait for MinCounter {
55    fn cmp(new_value: i64, current_value: i64) -> bool {
56        new_value < current_value
57    }
58
59    #[inline(always)]
60    fn counter(&self) -> &AtomicI64 {
61        &self.counter
62    }
63}
64
65#[derive(Serialize, Deserialize, Debug)]
66pub struct MaxCounter {
67    counter: AtomicI64,
68}
69
70impl From<i64> for MaxCounter {
71    fn from(value: i64) -> Self {
72        let counter = AtomicI64::new(value);
73        Self { counter }
74    }
75}
76
77impl Default for MaxCounter {
78    fn default() -> Self {
79        Self::new()
80    }
81}
82
83impl MaxCounter {
84    pub fn new() -> Self {
85        Self {
86            counter: AtomicI64::new(i64::MIN),
87        }
88    }
89}
90
91impl TimeCounterTrait for MaxCounter {
92    fn cmp(a: i64, b: i64) -> bool {
93        a > b
94    }
95    #[inline(always)]
96    fn counter(&self) -> &AtomicI64 {
97        &self.counter
98    }
99}
100
101#[cfg(test)]
102mod test {
103
104    use super::*;
105
106    #[test]
107    fn min_counter() {
108        let counter = MinCounter::new();
109        counter.update(0);
110        assert_eq!(counter.get(), 0);
111        counter.update(1);
112        assert_eq!(counter.get(), 0);
113        counter.update(0);
114        assert_eq!(counter.get(), 0);
115        counter.update(-1);
116        assert_eq!(counter.get(), -1);
117    }
118
119    #[test]
120    fn max_counter() {
121        let counter = MaxCounter::new();
122        counter.update(0);
123        assert_eq!(counter.get(), 0);
124        counter.update(-1);
125        assert_eq!(counter.get(), 0);
126        counter.update(0);
127        assert_eq!(counter.get(), 0);
128        counter.update(1);
129        assert_eq!(counter.get(), 1);
130    }
131}