use lockmap::LockMap;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::thread;
use std::time::Duration;
static BACKEND_LOADS: AtomicUsize = AtomicUsize::new(0);
fn load_from_backend(key: &str) -> String {
BACKEND_LOADS.fetch_add(1, Ordering::Relaxed);
thread::sleep(Duration::from_millis(100));
format!("value-of-{key}")
}
fn get_or_load(cache: &LockMap<String, String>, key: &str) -> String {
if let Some(value) = cache.get(key) {
return value;
}
let mut entry = cache.entry_by_ref(key);
entry.or_insert_with(|| load_from_backend(key)).clone()
}
fn main() {
let cache = LockMap::<String, String>::new();
thread::scope(|s| {
for i in 0..8 {
let cache = &cache;
s.spawn(move || {
let value = get_or_load(cache, "hot-key");
println!("thread {i}: got {value:?}");
});
}
});
let loads = BACKEND_LOADS.load(Ordering::Relaxed);
println!("backend loads for 8 concurrent requests: {loads}");
assert_eq!(loads, 1, "the backend must be hit exactly once");
}