pub struct CounterU8 { /* private fields */ }Expand description
An atomic counter using AtomicU8 / (core::u8).
§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 AtomicU8, 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<u8>
Implementations§
Source§impl CounterU8
impl CounterU8
Sourcepub const MAX: u8 = 255u8
pub const MAX: u8 = 255u8
Largest representable value
Sourcepub const MIN: u8 = 0u8
pub const MIN: u8 = 0u8
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: u8) -> Self
pub fn new_from_offset(offset: u8) -> Self
Instantiate with offset value
Sourcepub fn new_from_offset_with_ordering(offset: u8, ordering: Ordering) -> Self
pub fn new_from_offset_with_ordering(offset: u8, 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: u8,
counting_behavior: B,
) -> Self
pub fn new_from_offset_with_counting_behavior<B: Into<BitFlags<CountingBehavior>>>( offset: u8, counting_behavior: B, ) -> Self
Instantiate with offset value and counting behavior
Sourcepub fn get(&self) -> u8
pub fn get(&self) -> u8
Get current value with the default ordering
use width_counters::{ *, CounterU8 as C };
use u8 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) -> u8
pub fn get_with_ordering(&self, ordering: Ordering) -> u8
Get current value with a specific ordering
Source§impl CounterU8
impl CounterU8
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: u8)
pub fn inc_by(&self, amount: u8)
Increment by specified amount
use width_counters::{ *, CounterU8 as C };
use core::ops::*;
use u8 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: u8, ordering: Ordering)
pub fn inc_by_with_ordering(&self, amount: u8, ordering: Ordering)
Increment by specified amount with ordering
use width_counters::{ *, CounterU8 as C };
use u8 as U;
use core::ops::*;
let m = 3u8;
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) -> u8
pub fn get_and_inc_one(&self) -> u8
Combine the increment (by one) and get operations
Returns the value before the increment operation
Sourcepub fn get_and_inc_by(&self, amount: u8) -> u8
pub fn get_and_inc_by(&self, amount: u8) -> u8
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: u8, ordering: Ordering) -> u8
pub fn get_and_inc_by_with_ordering(&self, amount: u8, ordering: Ordering) -> u8
Combine the increment (by the given amount) and get operations
Returns the value before the increment operation
Source§impl CounterU8
impl CounterU8
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: u8)
pub fn dec_by(&self, amount: u8)
Decrement by specified amount
use width_counters::{ *, CounterU8 as C };
use core::ops::*;
use u8 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: u8, ordering: Ordering)
pub fn dec_by_with_ordering(&self, amount: u8, ordering: Ordering)
Decrement by specified amount with ordering
use width_counters::{ *, CounterU8 as C };
use u8 as U;
use core::ops::*;
let m = 3u8;
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) -> u8
pub fn get_and_dec_one(&self) -> u8
Combine the decrement (by one) and get operations
Returns the value before the decrement operation
Sourcepub fn get_and_dec_by(&self, amount: u8) -> u8
pub fn get_and_dec_by(&self, amount: u8) -> u8
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: u8, ordering: Ordering) -> u8
pub fn get_and_dec_by_with_ordering(&self, amount: u8, ordering: Ordering) -> u8
Combine the decrement (by the given amount) and get operations
Returns the value before the decrement operation
Trait Implementations§
Source§impl CountsNonmotonically for CounterU8
impl CountsNonmotonically for CounterU8
Source§fn inc_one(&self)
fn inc_one(&self)
Increment by one
use width_counters::{ *, CounterU8 as C };
use core::ops::*;
use enumflags2::{make_bitflags};
use u8 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::{*, CounterU8 as C, CountingBehavior as B };
use u8 as U;
use core::ops::*;
let m = 3u8;
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::{ *, CounterU8 as C };
use core::ops::*;
use enumflags2::{make_bitflags};
use u8 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::{*, CounterU8 as C, CountingBehavior as B };
use u8 as U;
use core::ops::*;
let m = 3u8;
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 HasCountingBehavior for CounterU8
impl HasCountingBehavior for CounterU8
fn get_behavior_ref(&self) -> &BitFlags<CountingBehavior>
fn get_behavior_conflicts(&self) -> AllCountingBehaviorConflicts
Source§impl Ord for CounterU8
impl Ord for CounterU8
Source§impl PartialEq for CounterU8
PartialEq is only equal when orderings and counting behaviors are equal
impl PartialEq for CounterU8
PartialEq is only equal when orderings and counting behaviors are equal
use width_counters::{ *, CounterU8 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 for CounterU8
PartialOrd only produces cmp ordering when atomic orderings are equal
impl PartialOrd for CounterU8
PartialOrd only produces cmp ordering when atomic orderings are equal
use width_counters::{ *, CounterU8 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");