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