Struct width_counters::CounterU32
source · pub struct CounterU32 { /* private fields */ }Expand description
An atomic counter using AtomicU32 / (core::u32).
Behavior
- The default ordering is Sequentially Consistent.
- The ordering used for atomic operations is customizable for operations ending in
with_ordering. - The choice of ordering intentionally impacts ALMOST EVERYTHING about how this counter works, including de/serialization, incrementing, decrementing, equality comparisons, partial ordering comparisons, etc.
- Total (non-partial) ordering comparisons always use the default ordering.
- Unlike the underlying AtomicU32, this will not wrap on overflow unless the cyclic behavior mode is set.
- The default behavior is non-monotonic, so the counter can increment and decrement.
Ordering
- PartialEq is implemented such that counters with differing orderings are never equal.
- PartialOrd is implemented such that counters with differing (atomic) orderings produce no (comparison) ordering.
- (Saturating) arithmetic operations are implemented such that differing atomic orderings between the operands are ignored!
Miscellaneous
You can use the to_x method to convert to any type that implements From<u32>
Implementations§
source§impl CounterU32
impl CounterU32
sourcepub const MAX: u32 = 4_294_967_295u32
pub const MAX: u32 = 4_294_967_295u32
Largest representable value
sourcepub const MIN: u32 = 0u32
pub const MIN: u32 = 0u32
Smallest representable value
sourcepub const DEFAULT_ORDERING: Ordering = Ordering::SeqCst
pub const DEFAULT_ORDERING: Ordering = Ordering::SeqCst
Default Atomic ordering
sourcepub const DEFAULT_COUNTING_BEHAVIOR: BitFlags<CountingBehavior> = _
pub const DEFAULT_COUNTING_BEHAVIOR: BitFlags<CountingBehavior> = _
Default counting behavior
sourcepub fn new_with_ordering(ordering: Ordering) -> Self
pub fn new_with_ordering(ordering: Ordering) -> Self
Instantiate with ordering
sourcepub fn new_from_offset(offset: u32) -> Self
pub fn new_from_offset(offset: u32) -> Self
Instantiate with offset value
sourcepub fn new_from_offset_with_ordering(offset: u32, ordering: Ordering) -> Self
pub fn new_from_offset_with_ordering(offset: u32, ordering: Ordering) -> Self
Instantiate with offset value and ordering
sourcepub fn set_counting_behavior<B: Into<BitFlags<CountingBehavior>>>(
&mut self,
counting_behavior: B
)
pub fn set_counting_behavior<B: Into<BitFlags<CountingBehavior>>>( &mut self, counting_behavior: B )
Set counting behavior
sourcepub fn new_with_counting_behavior<B: Into<BitFlags<CountingBehavior>>>(
counting_behavior: B
) -> Self
pub fn new_with_counting_behavior<B: Into<BitFlags<CountingBehavior>>>( counting_behavior: B ) -> Self
Instantiate with counting behaviors
sourcepub fn new_from_offset_with_counting_behavior<B: Into<BitFlags<CountingBehavior>>>(
offset: u32,
counting_behavior: B
) -> Self
pub fn new_from_offset_with_counting_behavior<B: Into<BitFlags<CountingBehavior>>>( offset: u32, counting_behavior: B ) -> Self
Instantiate with offset value and counting behavior
sourcepub fn get(&self) -> u32
pub fn get(&self) -> u32
Get current value with the default ordering
use width_counters::{ *, CounterU32 as C };
use u32 as U;
let c = C::new();
assert_eq!(c.get(), 0, "get returns initial value");
c.inc_one();
c.inc_one();
c.inc_one();
assert_eq!(c.get(), 3, "get returns post-increment value");sourcepub fn get_with_ordering(&self, ordering: Ordering) -> u32
pub fn get_with_ordering(&self, ordering: Ordering) -> u32
Get current value with a specific ordering
source§impl CounterU32
impl CounterU32
sourcepub fn inc_one_with_ordering(&self, ordering: Ordering)
pub fn inc_one_with_ordering(&self, ordering: Ordering)
Increment by one with ordering
sourcepub fn inc_by(&self, amount: u32)
pub fn inc_by(&self, amount: u32)
Increment by specified amount
use width_counters::{ *, CounterU32 as C };
use core::ops::*;
use u32 as U;
let offset = U::MAX/2;
let c = C::new_from_offset(offset);
let m = 20;
(0..m).for_each(|_| { c.inc_by(2); });
assert_eq!((c.get() as i128).sub((20*2) as i128), ((offset) as i128), "counter must Increment by specified amount");sourcepub fn inc_by_with_ordering(&self, amount: u32, ordering: Ordering)
pub fn inc_by_with_ordering(&self, amount: u32, ordering: Ordering)
Increment by specified amount with ordering
use width_counters::{ *, CounterU32 as C };
use u32 as U;
use core::ops::*;
let m = 3u32;
let d = C::new_from_offset(U::MAX.sub(m * 2));
d.inc_by(m);
d.inc_by(m);
d.inc_by(m);
assert_eq!(d.get(), U::MAX, "counter must stop at MAX");sourcepub fn get_and_inc_one(&self) -> u32
pub fn get_and_inc_one(&self) -> u32
Combine the increment (by one) and get operations
Returns the value before the increment operation
sourcepub fn get_and_inc_by(&self, amount: u32) -> u32
pub fn get_and_inc_by(&self, amount: u32) -> u32
Combine the increment (by the given amount) and get operations
Returns the value before the incrementoperation
sourcepub fn get_and_inc_by_with_ordering(
&self,
amount: u32,
ordering: Ordering
) -> u32
pub fn get_and_inc_by_with_ordering( &self, amount: u32, ordering: Ordering ) -> u32
Combine the increment (by the given amount) and get operations
Returns the value before the increment operation
source§impl CounterU32
impl CounterU32
sourcepub fn dec_one_with_ordering(&self, ordering: Ordering)
pub fn dec_one_with_ordering(&self, ordering: Ordering)
Decrement by one with ordering
sourcepub fn dec_by(&self, amount: u32)
pub fn dec_by(&self, amount: u32)
Decrement by specified amount
use width_counters::{ *, CounterU32 as C };
use core::ops::*;
use u32 as U;
let offset = U::MAX/2;
let c = C::new_from_offset(offset);
let m = 20;
(0..m).for_each(|_| { c.dec_by(2); });
assert_eq!((c.get() as i128).add((20*2) as i128), ((offset) as i128), "counter must Decrement by specified amount");sourcepub fn dec_by_with_ordering(&self, amount: u32, ordering: Ordering)
pub fn dec_by_with_ordering(&self, amount: u32, ordering: Ordering)
Decrement by specified amount with ordering
use width_counters::{ *, CounterU32 as C };
use u32 as U;
use core::ops::*;
let m = 3u32;
let d = C::new_from_offset(U::MIN.add(m * 2));
d.dec_by(m);
d.dec_by(m);
d.dec_by(m);
assert_eq!(d.get(), U::MIN, "counter must stop at MIN");sourcepub fn get_and_dec_one(&self) -> u32
pub fn get_and_dec_one(&self) -> u32
Combine the decrement (by one) and get operations
Returns the value before the decrement operation
sourcepub fn get_and_dec_by(&self, amount: u32) -> u32
pub fn get_and_dec_by(&self, amount: u32) -> u32
Combine the decrement (by the given amount) and get operations
Returns the value before the decrementoperation
sourcepub fn get_and_dec_by_with_ordering(
&self,
amount: u32,
ordering: Ordering
) -> u32
pub fn get_and_dec_by_with_ordering( &self, amount: u32, ordering: Ordering ) -> u32
Combine the decrement (by the given amount) and get operations
Returns the value before the decrement operation
Trait Implementations§
source§impl Add<CounterU32> for CounterU32
impl Add<CounterU32> for CounterU32
source§fn add(self, rhs: Self) -> Self::Output
fn add(self, rhs: Self) -> Self::Output
- This operation is implemented with saturating arithmetic
- This operation IGNORES dissimilar atomic orderings!
§type Output = CounterU32
type Output = CounterU32
+ operator.source§impl AsRef<Ordering> for CounterU32
impl AsRef<Ordering> for CounterU32
source§impl Clone for CounterU32
impl Clone for CounterU32
source§impl CountsNonmotonically for CounterU32
impl CountsNonmotonically for CounterU32
source§fn inc_one(&self)
fn inc_one(&self)
Increment by one
use width_counters::{ *, CounterU32 as C };
use core::ops::*;
use enumflags2::{make_bitflags};
use u32 as U;
let offset = U::MAX/2;
let c = C::new_from_offset(offset);
let m = 20;
(0..m).for_each(|_| { c.inc_one(); });
assert_eq!(c.get(), (offset).add(20), "counter must Increment/add number of times given as per sequential ordering");
let d = C::new_from_offset(U::MAX);
d.inc_one();
d.inc_one();
assert_eq!(d.get(), U::MAX, "counter must stop at MAX ");source§fn can_inc(&self) -> bool
fn can_inc(&self) -> bool
Can the counter increment any further?
- It halts increment ing at Self::MAX
use width_counters::{*, CounterU32 as C, CountingBehavior as B };
use u32 as U;
use core::ops::*;
let m = 3u32;
let offset = C::MAX/2;
let d = C::new_from_offset_with_counting_behavior(offset, B::Increment);
assert_eq!(d.can_inc(), true, "counter must detect when it can Increment");
let offset = C::MAX;
let d = C::new_from_offset_with_counting_behavior(offset, B::Increment);
assert_eq!(d.can_inc(), false, "counter must detect when it can no longer Increment");source§fn is_incrementable(&self) -> bool
fn is_incrementable(&self) -> bool
Is the current index advanceable with the given operation type
source§fn is_within_increment_bound(&self) -> bool
fn is_within_increment_bound(&self) -> bool
Is it within(inclusive) the increment bound
- The bound is: Self::MAX
- The bound never applies in:** acyclic mode
source§fn is_at_increment_bound(&self) -> bool
fn is_at_increment_bound(&self) -> bool
Is it at the increment bound
- The bound is: Self::MAX
source§fn dec_one(&self)
fn dec_one(&self)
Decrement by one
use width_counters::{ *, CounterU32 as C };
use core::ops::*;
use enumflags2::{make_bitflags};
use u32 as U;
let offset = U::MAX/2;
let c = C::new_from_offset(offset);
let m = 20;
(0..m).for_each(|_| { c.dec_one(); });
assert_eq!(c.get(), (offset).sub(20), "counter must Decrement/sub number of times given as per sequential ordering");
let d = C::new_from_offset(U::MIN);
d.dec_one();
d.dec_one();
assert_eq!(d.get(), U::MIN, "counter must stop at MIN ");source§fn can_dec(&self) -> bool
fn can_dec(&self) -> bool
Can the counter decrement any further?
- It halts decrement ing at Self::MIN
use width_counters::{*, CounterU32 as C, CountingBehavior as B };
use u32 as U;
use core::ops::*;
let m = 3u32;
let offset = C::MAX/2;
let d = C::new_from_offset_with_counting_behavior(offset, B::Decrement);
assert_eq!(d.can_dec(), true, "counter must detect when it can Decrement");
let offset = C::MIN;
let d = C::new_from_offset_with_counting_behavior(offset, B::Decrement);
assert_eq!(d.can_dec(), false, "counter must detect when it can no longer Decrement");source§fn is_decrementable(&self) -> bool
fn is_decrementable(&self) -> bool
Is the current index advanceable with the given operation type
source§fn is_within_decrement_bound(&self) -> bool
fn is_within_decrement_bound(&self) -> bool
Is it within(inclusive) the decrement bound
- The bound is: Self::MIN
- The bound never applies in:** acyclic mode
source§fn is_at_decrement_bound(&self) -> bool
fn is_at_decrement_bound(&self) -> bool
Is it at the decrement bound
- The bound is: Self::MIN
source§impl Debug for CounterU32
impl Debug for CounterU32
source§impl Default for CounterU32
impl Default for CounterU32
source§impl Display for CounterU32
impl Display for CounterU32
source§impl Div<CounterU32> for CounterU32
impl Div<CounterU32> for CounterU32
source§fn div(self, rhs: Self) -> Self::Output
fn div(self, rhs: Self) -> Self::Output
- This operation is implemented with saturating arithmetic
- This operation IGNORES dissimilar atomic orderings!
§type Output = CounterU32
type Output = CounterU32
/ operator.source§impl From<&CounterU32> for u32
impl From<&CounterU32> for u32
source§fn from(counter: &CounterU32) -> Self
fn from(counter: &CounterU32) -> Self
source§impl From<u32> for CounterU32
impl From<u32> for CounterU32
source§impl HasCountingBehavior for CounterU32
impl HasCountingBehavior for CounterU32
fn get_behavior_ref(&self) -> &BitFlags<CountingBehavior>
fn get_behavior_conflicts(&self) -> AllCountingBehaviorConflicts
source§impl Hash for CounterU32
impl Hash for CounterU32
source§impl IsCounter for CounterU32
impl IsCounter for CounterU32
source§impl Mul<CounterU32> for CounterU32
impl Mul<CounterU32> for CounterU32
source§fn mul(self, rhs: Self) -> Self::Output
fn mul(self, rhs: Self) -> Self::Output
- This operation is implemented with saturating arithmetic
- This operation IGNORES dissimilar atomic orderings!
§type Output = CounterU32
type Output = CounterU32
* operator.source§impl Ord for CounterU32
impl Ord for CounterU32
source§impl PartialEq<CounterU32> for CounterU32
impl PartialEq<CounterU32> for CounterU32
PartialEq is only equal when orderings and counting behaviors are equal
use width_counters::{ *, CounterU32 as C };
use core::sync::atomic::Ordering;
let a = C::new_from_offset_with_ordering(33, Ordering::Relaxed);
let b = C::new_from_offset_with_ordering(33, Ordering::Relaxed);
assert_eq!(a, b, "counters must be equal when counts and orderings are equal");
assert_eq!(a, b, "counters must be equal when counts and orderings are equal");
let m = 20;
(0..m).for_each(|_| { a.inc_one(); b.inc_one(); });
assert_eq!(a, b, "counters must be equal after counting same amount");
assert_eq!(a, b, "counters must be equal after counting same amount");
a.inc_one();
assert_ne!(a, b, "counters must not be equal after counting different amounts");
let c = C::new_from_offset_with_ordering(44, Ordering::Relaxed);
let d = C::new_from_offset_with_ordering(44, Ordering::Release);
assert_ne!(c, d, "ordering-inequal counters must not be equal with same count");source§impl PartialOrd<CounterU32> for CounterU32
impl PartialOrd<CounterU32> for CounterU32
PartialOrd only produces cmp ordering when atomic orderings are equal
use width_counters::{ *, CounterU32 as C };
use core::sync::atomic::Ordering;
let a = C::new_from_offset_with_ordering(32, Ordering::Relaxed);
let b = C::new_from_offset_with_ordering(33, Ordering::Relaxed);
assert!(a < b, "same-cmp::ordering counters must be ordered by when counts");
assert!(b > a, "same-cmp::ordering counters must be ordered by when counts");
let m = 20;
(0..m).for_each(|_| { a.inc_one(); b.inc_one(); });
assert!(a < b, "cmp::ordering preserved after counting same amount");
assert!(b > a, "cmp::ordering preserved after counting same amount");1.0.0 · source§fn le(&self, other: &Rhs) -> bool
fn le(&self, other: &Rhs) -> bool
self and other) and is used by the <=
operator. Read moresource§impl Sub<CounterU32> for CounterU32
impl Sub<CounterU32> for CounterU32
source§fn sub(self, rhs: Self) -> Self::Output
fn sub(self, rhs: Self) -> Self::Output
- This operation is implemented with saturating arithmetic
- This operation IGNORES dissimilar atomic orderings!
§type Output = CounterU32
type Output = CounterU32
- operator.