Struct width_counters::CounterI32
source · pub struct CounterI32 { /* private fields */ }Expand description
An atomic counter using AtomicI32 / (core::i32).
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 AtomicI32, 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<i32>
Implementations§
source§impl CounterI32
impl CounterI32
sourcepub const MAX: i32 = 2_147_483_647i32
pub const MAX: i32 = 2_147_483_647i32
Largest representable value
sourcepub const MIN: i32 = -2_147_483_648i32
pub const MIN: i32 = -2_147_483_648i32
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: i32) -> Self
pub fn new_from_offset(offset: i32) -> Self
Instantiate with offset value
sourcepub fn new_from_offset_with_ordering(offset: i32, ordering: Ordering) -> Self
pub fn new_from_offset_with_ordering(offset: i32, 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: i32,
counting_behavior: B
) -> Self
pub fn new_from_offset_with_counting_behavior<B: Into<BitFlags<CountingBehavior>>>( offset: i32, counting_behavior: B ) -> Self
Instantiate with offset value and counting behavior
sourcepub fn get(&self) -> i32
pub fn get(&self) -> i32
Get current value with the default ordering
use width_counters::{ *, CounterI32 as C };
use i32 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) -> i32
pub fn get_with_ordering(&self, ordering: Ordering) -> i32
Get current value with a specific ordering
source§impl CounterI32
impl CounterI32
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: i32)
pub fn inc_by(&self, amount: i32)
Increment by specified amount
use width_counters::{ *, CounterI32 as C };
use core::ops::*;
use i32 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: i32, ordering: Ordering)
pub fn inc_by_with_ordering(&self, amount: i32, ordering: Ordering)
Increment by specified amount with ordering
use width_counters::{ *, CounterI32 as C };
use i32 as U;
use core::ops::*;
let m = 3i32;
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) -> i32
pub fn get_and_inc_one(&self) -> i32
Combine the increment (by one) and get operations
Returns the value before the increment operation
sourcepub fn get_and_inc_by(&self, amount: i32) -> i32
pub fn get_and_inc_by(&self, amount: i32) -> i32
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: i32,
ordering: Ordering
) -> i32
pub fn get_and_inc_by_with_ordering( &self, amount: i32, ordering: Ordering ) -> i32
Combine the increment (by the given amount) and get operations
Returns the value before the increment operation
source§impl CounterI32
impl CounterI32
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: i32)
pub fn dec_by(&self, amount: i32)
Decrement by specified amount
use width_counters::{ *, CounterI32 as C };
use core::ops::*;
use i32 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: i32, ordering: Ordering)
pub fn dec_by_with_ordering(&self, amount: i32, ordering: Ordering)
Decrement by specified amount with ordering
use width_counters::{ *, CounterI32 as C };
use i32 as U;
use core::ops::*;
let m = 3i32;
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) -> i32
pub fn get_and_dec_one(&self) -> i32
Combine the decrement (by one) and get operations
Returns the value before the decrement operation
sourcepub fn get_and_dec_by(&self, amount: i32) -> i32
pub fn get_and_dec_by(&self, amount: i32) -> i32
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: i32,
ordering: Ordering
) -> i32
pub fn get_and_dec_by_with_ordering( &self, amount: i32, ordering: Ordering ) -> i32
Combine the decrement (by the given amount) and get operations
Returns the value before the decrement operation
Trait Implementations§
source§impl Add<CounterI32> for CounterI32
impl Add<CounterI32> for CounterI32
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 = CounterI32
type Output = CounterI32
+ operator.source§impl AsRef<Ordering> for CounterI32
impl AsRef<Ordering> for CounterI32
source§impl Clone for CounterI32
impl Clone for CounterI32
source§impl CountsNonmotonically for CounterI32
impl CountsNonmotonically for CounterI32
source§fn inc_one(&self)
fn inc_one(&self)
Increment by one
use width_counters::{ *, CounterI32 as C };
use core::ops::*;
use enumflags2::{make_bitflags};
use i32 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::{*, CounterI32 as C, CountingBehavior as B };
use i32 as U;
use core::ops::*;
let m = 3i32;
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::{ *, CounterI32 as C };
use core::ops::*;
use enumflags2::{make_bitflags};
use i32 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::{*, CounterI32 as C, CountingBehavior as B };
use i32 as U;
use core::ops::*;
let m = 3i32;
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 CounterI32
impl Debug for CounterI32
source§impl Default for CounterI32
impl Default for CounterI32
source§impl Display for CounterI32
impl Display for CounterI32
source§impl Div<CounterI32> for CounterI32
impl Div<CounterI32> for CounterI32
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 = CounterI32
type Output = CounterI32
/ operator.source§impl From<&CounterI32> for i32
impl From<&CounterI32> for i32
source§fn from(counter: &CounterI32) -> Self
fn from(counter: &CounterI32) -> Self
source§impl From<i32> for CounterI32
impl From<i32> for CounterI32
source§impl HasCountingBehavior for CounterI32
impl HasCountingBehavior for CounterI32
fn get_behavior_ref(&self) -> &BitFlags<CountingBehavior>
fn get_behavior_conflicts(&self) -> AllCountingBehaviorConflicts
source§impl Hash for CounterI32
impl Hash for CounterI32
source§impl IsCounter for CounterI32
impl IsCounter for CounterI32
source§impl Mul<CounterI32> for CounterI32
impl Mul<CounterI32> for CounterI32
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 = CounterI32
type Output = CounterI32
* operator.source§impl Ord for CounterI32
impl Ord for CounterI32
source§impl PartialEq<CounterI32> for CounterI32
impl PartialEq<CounterI32> for CounterI32
PartialEq is only equal when orderings and counting behaviors are equal
use width_counters::{ *, CounterI32 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<CounterI32> for CounterI32
impl PartialOrd<CounterI32> for CounterI32
PartialOrd only produces cmp ordering when atomic orderings are equal
use width_counters::{ *, CounterI32 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<CounterI32> for CounterI32
impl Sub<CounterI32> for CounterI32
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 = CounterI32
type Output = CounterI32
- operator.