use crdtosphere::prelude::*;
use std::sync::Arc;
use std::thread;
fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("CRDTosphere Atomic PNCounter Example");
println!("====================================");
#[cfg(not(feature = "hardware-atomic"))]
{
println!("Standard (non-atomic) implementation:");
println!("- Requires &mut self for modifications");
println!("- Single-threaded access only");
let mut counter = PNCounter::<DefaultConfig>::new(1);
counter.increment(10)?;
counter.decrement(3)?;
println!("Counter value: {}", counter.value());
}
#[cfg(feature = "hardware-atomic")]
{
println!("Atomic implementation:");
println!("- Allows &self for modifications");
println!("- Multi-threaded safe with Arc<T>");
println!("- Supports concurrent increment/decrement");
let counter = Arc::new(PNCounter::<DefaultConfig>::new(1));
let handles: Vec<_> = (0..4)
.map(|i| {
let counter_clone = Arc::clone(&counter);
thread::spawn(move || {
for j in 0..10 {
if j % 2 == 0 {
counter_clone.increment(2).unwrap();
} else {
counter_clone.decrement(1).unwrap();
}
}
println!("Thread {} completed", i);
})
})
.collect();
for handle in handles {
handle.join().unwrap();
}
println!("Final counter value: {}", counter.value());
println!("Expected: 40 (4 threads × (5×2 - 5×1) = 4 × 5 = 20)");
println!("Positive total: {}", counter.total_positive());
println!("Negative total: {}", counter.total_negative());
let counter2 = Arc::new(PNCounter::<DefaultConfig>::new(2));
counter2.increment(15).unwrap();
counter2.decrement(5).unwrap();
let mut counter_clone = counter.as_ref().clone();
counter_clone.merge(&*counter2).unwrap();
println!("After merge with counter2 (+15, -5):");
println!("Merged counter value: {}", counter_clone.value());
println!(
"Expected: {} + 10 = {}",
counter.value(),
counter.value() + 10
);
}
Ok(())
}