use std::thread;
mod counters {
use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};
pub(crate) trait Counter {
fn increment(&mut self);
fn local_count(&self) -> usize;
fn global_count(&self) -> usize;
}
pub(crate) struct EventCounter {
local_count: usize,
global_count: Arc<AtomicUsize>,
}
impl EventCounter {
pub(crate) fn new_as_counter() -> linked::Box<dyn Counter> {
let global_count = Arc::new(AtomicUsize::new(0));
linked::new_box!(
dyn Counter,
Self {
local_count: 0,
global_count: Arc::clone(&global_count),
}
)
}
}
impl Counter for EventCounter {
fn increment(&mut self) {
self.local_count = self.local_count.saturating_add(1);
self.global_count.fetch_add(1, Ordering::Relaxed);
}
fn local_count(&self) -> usize {
self.local_count
}
fn global_count(&self) -> usize {
self.global_count.load(Ordering::Relaxed)
}
}
}
use counters::{Counter, EventCounter};
linked::instances!(static RECORDS_PROCESSED: linked::Box<dyn Counter> = EventCounter::new_as_counter());
fn main() {
const THREAD_COUNT: usize = 4;
const RECORDS_PER_THREAD: usize = 1_000;
let mut threads = Vec::with_capacity(THREAD_COUNT);
for _ in 0..THREAD_COUNT {
threads.push(thread::spawn(move || {
let mut counter = RECORDS_PROCESSED.get();
for _ in 0..RECORDS_PER_THREAD {
counter.increment();
}
println!(
"Thread completed work; local count: {}, global count: {}",
counter.local_count(),
counter.global_count()
);
}));
}
for thread in threads {
thread.join().unwrap();
}
let final_count = RECORDS_PROCESSED.get().global_count();
println!("All threads completed work; final global count: {final_count}");
}