Struct width_counters::CounterUsize
source · pub struct CounterUsize { /* private fields */ }Expand description
An atomic counter using AtomicUsize / (core::usize).
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 AtomicUsize, this will not wrap on overflow.
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<usize>
Implementations§
source§impl CounterUsize
impl CounterUsize
sourcepub const MAX: usize = 18_446_744_073_709_551_615usize
pub const MAX: usize = 18_446_744_073_709_551_615usize
Largest representable value
sourcepub const MIN: usize = 0usize
pub const MIN: usize = 0usize
Smallest representable value
sourcepub const DEFAULT_ORDERING: Ordering = Ordering::SeqCst
pub const DEFAULT_ORDERING: Ordering = Ordering::SeqCst
Default Atomic ordering
sourcepub const fn new_with_ordering(ordering: Ordering) -> Self
pub const fn new_with_ordering(ordering: Ordering) -> Self
Instantiate with ordering
sourcepub const fn new_from_offset(offset: usize) -> Self
pub const fn new_from_offset(offset: usize) -> Self
Instantiate with offset value
sourcepub const fn new_from_offset_with_ordering(
offset: usize,
ordering: Ordering
) -> Self
pub const fn new_from_offset_with_ordering( offset: usize, ordering: Ordering ) -> Self
Instantiate with offset value and ordering
sourcepub fn get(&self) -> usize
pub fn get(&self) -> usize
Get current value with the default ordering
use width_counters::{CounterUsize as C };
use usize 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) -> usize
pub fn get_with_ordering(&self, ordering: Ordering) -> usize
Get current value with a specific ordering
source§impl CounterUsize
impl CounterUsize
sourcepub fn inc_one(&self)
pub fn inc_one(&self)
Increment by one
use width_counters::{CounterUsize as C };
use core::ops::*;
use usize 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 ");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: usize)
pub fn inc_by(&self, amount: usize)
Increment by specified amount
use width_counters::{CounterUsize as C };
use core::ops::*;
use usize 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: usize, ordering: Ordering)
pub fn inc_by_with_ordering(&self, amount: usize, ordering: Ordering)
Increment by specified amount with ordering
use width_counters::{CounterUsize as C };
use usize as U;
use core::ops::*;
let m = 3usize;
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 can_inc(&self) -> bool
pub fn can_inc(&self) -> bool
Can the counter Incrementany further?
- It halts incrementing at Self::MAX
use width_counters::{CounterUsize as C };
use usize as U;
use core::ops::*;
let m = 3usize;
let offset = C::MAX/2;
let d = C::new_from_offset(offset);
assert_eq!(d.can_inc(), true, "counter must detect when it can Increment");
let offset = C::MAX;
let d = C::new_from_offset(offset);
assert_eq!(d.can_inc(), false, "counter must detect when it can no longer Increment");sourcepub fn get_and_inc_one(&self) -> usize
pub fn get_and_inc_one(&self) -> usize
Combine the increment (by one) and get operations
Returns the value before the incrementoperation
sourcepub fn get_and_inc_by(&self, amount: usize) -> usize
pub fn get_and_inc_by(&self, amount: usize) -> usize
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: usize,
ordering: Ordering
) -> usize
pub fn get_and_inc_by_with_ordering( &self, amount: usize, ordering: Ordering ) -> usize
Combine the increment (by the given amount) and get operations
Returns the value before the incrementoperation
source§impl CounterUsize
impl CounterUsize
sourcepub fn dec_one(&self)
pub fn dec_one(&self)
Decrement by one
use width_counters::{CounterUsize as C };
use core::ops::*;
use usize 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 ");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: usize)
pub fn dec_by(&self, amount: usize)
Decrement by specified amount
use width_counters::{CounterUsize as C };
use core::ops::*;
use usize 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: usize, ordering: Ordering)
pub fn dec_by_with_ordering(&self, amount: usize, ordering: Ordering)
Decrement by specified amount with ordering
use width_counters::{CounterUsize as C };
use usize as U;
use core::ops::*;
let m = 3usize;
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 can_dec(&self) -> bool
pub fn can_dec(&self) -> bool
Can the counter Decrementany further?
- It halts decrementing at Self::MIN
use width_counters::{CounterUsize as C };
use usize as U;
use core::ops::*;
let m = 3usize;
let offset = C::MAX/2;
let d = C::new_from_offset(offset);
assert_eq!(d.can_dec(), true, "counter must detect when it can Decrement");
let offset = C::MIN;
let d = C::new_from_offset(offset);
assert_eq!(d.can_dec(), false, "counter must detect when it can no longer Decrement");sourcepub fn get_and_dec_one(&self) -> usize
pub fn get_and_dec_one(&self) -> usize
Combine the decrement (by one) and get operations
Returns the value before the decrementoperation
sourcepub fn get_and_dec_by(&self, amount: usize) -> usize
pub fn get_and_dec_by(&self, amount: usize) -> usize
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: usize,
ordering: Ordering
) -> usize
pub fn get_and_dec_by_with_ordering( &self, amount: usize, ordering: Ordering ) -> usize
Combine the decrement (by the given amount) and get operations
Returns the value before the decrementoperation
Trait Implementations§
source§impl Add<CounterUsize> for CounterUsize
impl Add<CounterUsize> for CounterUsize
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 = CounterUsize
type Output = CounterUsize
+ operator.source§impl AsRef<Ordering> for CounterUsize
impl AsRef<Ordering> for CounterUsize
source§impl Clone for CounterUsize
impl Clone for CounterUsize
source§impl Debug for CounterUsize
impl Debug for CounterUsize
source§impl Default for CounterUsize
impl Default for CounterUsize
source§impl Display for CounterUsize
impl Display for CounterUsize
source§impl Div<CounterUsize> for CounterUsize
impl Div<CounterUsize> for CounterUsize
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 = CounterUsize
type Output = CounterUsize
/ operator.source§impl From<&CounterUsize> for usize
impl From<&CounterUsize> for usize
source§fn from(counter: &CounterUsize) -> Self
fn from(counter: &CounterUsize) -> Self
source§impl From<usize> for CounterUsize
impl From<usize> for CounterUsize
source§impl Hash for CounterUsize
impl Hash for CounterUsize
source§impl Mul<CounterUsize> for CounterUsize
impl Mul<CounterUsize> for CounterUsize
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 = CounterUsize
type Output = CounterUsize
* operator.source§impl Ord for CounterUsize
impl Ord for CounterUsize
source§impl PartialEq<CounterUsize> for CounterUsize
impl PartialEq<CounterUsize> for CounterUsize
PartialEq is only equal when orderings are equal
use width_counters::{CounterUsize 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<CounterUsize> for CounterUsize
impl PartialOrd<CounterUsize> for CounterUsize
PartialOrd only produces cmp ordering when atomic orderings are equal
use width_counters::{CounterUsize 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<CounterUsize> for CounterUsize
impl Sub<CounterUsize> for CounterUsize
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 = CounterUsize
type Output = CounterUsize
- operator.