global_counter
Documentation
Sometimes you just want to count something globally, and you really dont want to worry to much about data races, other race conditions, all the fun stuff.
That's what this crate is for. It supplies global counters, which build on thoroughly tested synchronization primitives, namely parking_lot
s Mutex for the generic counter and the stdlibs atomic types for the primitive counters.
Usage
Add the following dependency to your Cargo.toml file:
[dependencies]
global_counter = "0.1.3"
Use the #[macro_use]
annotation when importing, like this:
#[macro_use]
extern crate global_counter;
Examples
#[macro_use]
extern crate global_counter;
use global_counter::generic::Inc;
use std::collections::LinkedList;
use std::iter::FromIterator;
#[derive(Debug, PartialEq, Eq)]
struct CardinalityCountedList(LinkedList<()>);
impl Inc for CardinalityCountedList {
fn inc(&mut self) {
self.0.push_back(());
}
}
impl CardinalityCountedList {
pub fn with_cardinality(card: usize) -> Self {
CardinalityCountedList(LinkedList::from_iter(std::iter::repeat(()).take(card)))
}
pub fn card(&self) -> usize {
self.0.len()
}
}
global_counter!(
COUNTER,
CardinalityCountedList,
CardinalityCountedList::with_cardinality(0)
);
fn main() {
assert_eq!((*COUNTER.get_borrowed()).card(), 0);
let t1 = std::thread::spawn(move || {
for _ in 0..(1 << 20) {
COUNTER.inc();
}
});
let t2 = std::thread::spawn(move || {
for _ in 0..(1 << 20) {
COUNTER.inc();
}
});
t1.join().unwrap();
let card = (*COUNTER.get_borrowed()).card();
assert!((1 << 20) <= card && card <= (2 << 20));
t2.join().unwrap();
assert_eq!((*COUNTER.get_borrowed()).card(), 2 << 20);
}
#[macro_use]
extern crate global_counter;
use global_counter::primitive::CounterUsize;
use std::sync::{Arc, Mutex};
fn main() {
static COUNTER: CounterUsize = CounterUsize::new(0);
let from = Arc::new(Mutex::new(vec![1, 5, 22, 10000, 43, -4, 39, 1, 2]));
let to = Arc::new(Mutex::new(vec![0, 0, 0, 0, 0, 0, 0, 0, 0]));
let to_arc = to.clone();
let from_arc = from.clone();
let t1 = std::thread::spawn(move || {
let indices = [COUNTER.inc(), COUNTER.inc(), COUNTER.inc()];
for &i in indices.iter() {
to_arc.lock().unwrap()[i] = from_arc.lock().unwrap()[i];
}
});
let to_arc = to.clone();
let from_arc = from.clone();
let t2 = std::thread::spawn(move || {
let indices = [COUNTER.inc(), COUNTER.inc(), COUNTER.inc()];
for &i in indices.iter() {
to_arc.lock().unwrap()[i] = from_arc.lock().unwrap()[i];
}
});
let indices = [COUNTER.inc(), COUNTER.inc(), COUNTER.inc()];
for &i in indices.iter() {
to.lock().unwrap()[i] = from.lock().unwrap()[i];
}
t1.join().unwrap();
t2.join().unwrap();
assert_eq!(**to.lock().unwrap(), **from.lock().unwrap());
}
License
Licensed under either of
at your option.
Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any
additional terms or conditions.