]>
Commit | Line | Data |
---|---|---|
064997fb FG |
1 | //! limit defines a struct to enforce limits. |
2 | ||
3 | #![warn(rust_2018_idioms, unused_lifetimes, semicolon_in_expressions_from_macros)] | |
4 | ||
5 | #[cfg(feature = "tracking")] | |
6 | use std::sync::atomic::AtomicUsize; | |
7 | ||
8 | /// Represents a struct used to enforce a numerical limit. | |
9 | pub struct Limit { | |
10 | upper_bound: usize, | |
11 | #[cfg(feature = "tracking")] | |
12 | max: AtomicUsize, | |
13 | } | |
14 | ||
15 | impl Limit { | |
16 | /// Creates a new limit. | |
17 | #[inline] | |
18 | pub const fn new(upper_bound: usize) -> Self { | |
19 | Self { | |
20 | upper_bound, | |
21 | #[cfg(feature = "tracking")] | |
22 | max: AtomicUsize::new(0), | |
23 | } | |
24 | } | |
25 | ||
26 | /// Creates a new limit. | |
27 | #[inline] | |
28 | #[cfg(feature = "tracking")] | |
29 | pub const fn new_tracking(upper_bound: usize) -> Self { | |
30 | Self { | |
31 | upper_bound, | |
32 | #[cfg(feature = "tracking")] | |
33 | max: AtomicUsize::new(1), | |
34 | } | |
35 | } | |
36 | ||
37 | /// Gets the underlying numeric limit. | |
38 | #[inline] | |
39 | pub const fn inner(&self) -> usize { | |
40 | self.upper_bound | |
41 | } | |
42 | ||
43 | /// Checks whether the given value is below the limit. | |
44 | /// Returns `Ok` when `other` is below `self`, and `Err` otherwise. | |
45 | #[inline] | |
46 | pub fn check(&self, other: usize) -> Result<(), ()> { | |
47 | if other > self.upper_bound { | |
48 | Err(()) | |
49 | } else { | |
50 | #[cfg(feature = "tracking")] | |
51 | loop { | |
52 | use std::sync::atomic::Ordering; | |
53 | let old_max = self.max.load(Ordering::Relaxed); | |
54 | if other <= old_max || old_max == 0 { | |
55 | break; | |
56 | } | |
57 | if self | |
58 | .max | |
59 | .compare_exchange_weak(old_max, other, Ordering::Relaxed, Ordering::Relaxed) | |
60 | .is_ok() | |
61 | { | |
f25598a0 | 62 | eprintln!("new max: {other}"); |
064997fb FG |
63 | } |
64 | } | |
65 | ||
66 | Ok(()) | |
67 | } | |
68 | } | |
69 | } |