Skip to content

Instantly share code, notes, and snippets.

@rust-play
Created August 5, 2020 16:24
Show Gist options
  • Save rust-play/2c8467dcfaaeed488ed558cd5f3a2656 to your computer and use it in GitHub Desktop.
Save rust-play/2c8467dcfaaeed488ed558cd5f3a2656 to your computer and use it in GitHub Desktop.
Code shared from the Rust Playground
use std::sync::Mutex;
use std::sync::RwLock;
use std::sync::Arc;
use std::collections::HashMap;
use lazy_static::lazy_static;
lazy_static! {
static ref CACHE: Mutex<HashMap<&'static str, Arc<RwLock<u32>>>> = Mutex::new(HashMap::new());
}
fn get(key: &'static str) -> u32 {
let entry_guard;
let mut entry;
// global lock
let mut c = CACHE.lock().unwrap();
if let Some(e) = c.get(key) {
// block if value still is beign produced (entry_guard write lock)
println!("[{:?}] wait", std::thread::current().id());
let v = *e.read().unwrap();
println!("[{:?}] hit: {}", std::thread::current().id(), v);
return v
} else {
c.insert(key, Arc::new(RwLock::new(0)));
entry_guard = c.get(key).unwrap().clone();
// lock entry before releasing global lock so stub value cannot be observed
entry = entry_guard.write().unwrap();
}
// unlock global
drop(c);
println!("[{:?}] miss: {}", std::thread::current().id(), &entry);
std::thread::sleep(std::time::Duration::from_secs(2));
let v = 1;
*entry = v;
println!("[{:?}] cached: {}", std::thread::current().id(), v);
// unlock entry
drop(entry);
v
}
fn main() {
let t1 = std::thread::spawn(|| {
dbg![get("foo")];
dbg![get("foo")];
});
let t2 = std::thread::spawn(|| {
dbg![get("foo")];
dbg![get("foo")];
});
t1.join().unwrap();
t2.join().unwrap();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment