# global_counter
[Documentation](https://docs.rs/global_counter/*/global_counter/)
This crate implements global counters, generic and primitive, which build on thoroughly tested synchronization primitives, namely `parking_lot`s Mutex (by default) and the stdlibs atomic types. Faster counters, which trade accuracy for performance are also available.
## Usage
Add the following dependency to your Cargo.toml file:
```toml
[dependencies]
global_counter = "0.2.0"
```
Use the `#[macro_use]` annotation when importing, like this:
```rust
#[macro_use]
extern crate global_counter;
```
If you want to disable using `parking_lot`, and instead use the stdlibs Mutex, disable the default features:
```toml
[dependencies.global_counter]
version = "0.2.0"
default-features = false
```
## Quickstart
### Create a counter
```rust
// Generic
global_counter!(COUTER_NAME, CountedType, CountedType::default());
// Primitive
static COUNTER_NAME : CounterI16 = CounterI16::new(0);
```
### Count your counter up
```rust
COUNTER_NAME.inc();
```
### Get the value of your counter
```rust
// Generic
let val = COUNTER_NAME.get_cloned();
// Primitive
let val = COUNTER_NAME.get();
```
## Example - No cloning of counted struct
```rust
#[macro_use]
extern crate global_counter;
use global_counter::generic::Inc;
use std::collections::LinkedList;
use std::iter::FromIterator;
// Note how this (supposedly) doesnt implement `Clone`.
#[derive(Debug, PartialEq, Eq)]
struct CardinalityCountedList(LinkedList<()>);
// Incrementing to us means just inserting another element.
impl Inc for CardinalityCountedList {
fn inc(&mut self) {
self.0.push_back(());
}
}
// Some helper methods.
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()
}
}
// We create a new global, thread-safe Counter.
// Could also do this in the main fn.
global_counter!(
COUNTER,
CardinalityCountedList,
CardinalityCountedList::with_cardinality(0)
);
fn main() {
// Note how we use a borrow, but never clone this LinkedList.
// Of course, a cloning, convenient API is also available.
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();
// t1 finished, t2 maybe did something.
assert!((1 << 20) <= card && card <= (2 << 20));
t2.join().unwrap();
// Both threads finished, the counter guarantees `Inc` was executed 2 << 20 times.
assert_eq!((*COUNTER.get_borrowed()).card(), 2 << 20);
}
```
## Example - Primitive counter used for indexing into vec from multiple threads
```rust
#[macro_use]
extern crate global_counter;
use global_counter::primitive::exact::CounterUsize;
use std::sync::{Arc, Mutex};
fn main() {
// This is a primitive counter. Implemented using atomics, more efficient than its generic equivalent.
// Available for primitive integer types.
static COUNTER: CounterUsize = CounterUsize::new(0);
// We want to copy the 'from' arr to the 'to' arr. From multiple threads.
// Please don't do this in actual code.
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]));
// 3 elemets in two other threads + 3 elements in this thread.
// After joining those two threads, all elements will have been copied.
let to_arc = to.clone();
let from_arc = from.clone();
let t1 = std::thread::spawn(move || {
// '.inc()' increments the counter, returning the previous value.
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
* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
* MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
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.