#![allow(clippy::new_without_default, reason = "Not relevant for example")]
use std::thread;
use linked::Object;
mod counters {
use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};
#[linked::object]
pub(crate) struct EventCounter {
local_count: usize,
global_count: Arc<AtomicUsize>,
}
impl EventCounter {
pub(crate) fn new() -> Self {
let global_count = Arc::new(AtomicUsize::new(0));
linked::new!(Self {
local_count: 0,
global_count: Arc::clone(&global_count),
})
}
pub(crate) fn increment(&mut self) {
self.local_count = self.local_count.saturating_add(1);
self.global_count.fetch_add(1, Ordering::Relaxed);
}
pub(crate) fn local_count(&self) -> usize {
self.local_count
}
pub(crate) fn global_count(&self) -> usize {
self.global_count.load(Ordering::Relaxed)
}
}
}
use counters::EventCounter;
fn main() {
const THREAD_COUNT: usize = 4;
const RECORDS_PER_THREAD: usize = 1_000;
let mut threads = Vec::with_capacity(THREAD_COUNT);
let counter = EventCounter::new();
let counter_family = counter.family();
for _ in 0..THREAD_COUNT {
threads.push(thread::spawn({
let counter_family = counter_family.clone();
move || {
let mut counter: EventCounter = counter_family.into();
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 = counter.global_count();
println!("All threads completed work; final global count: {final_count}");
}