in pkcs11/pkcs11/src/context.rs [647:683]
fn weak_cache_get_or_insert<K, V, F, E>(
cache: &std::sync::Mutex<std::collections::BTreeMap<K, std::sync::Weak<V>>>,
key: K,
value: F,
) -> Result<std::sync::Arc<V>, E>
where
K: std::cmp::Ord,
F: FnOnce(&K) -> Result<V, E>,
{
match cache.lock().unwrap().entry(key) {
std::collections::btree_map::Entry::Occupied(mut entry) => {
let weak = entry.get();
if let Some(strong) = weak.upgrade() {
// Created this value before, and someone still has a strong reference to it, so we were able to upgrade our weak reference
// to a new strong reference. Return this new strong reference.
Ok(strong)
} else {
// Created this value before, but all the strong references to it have been dropped since then.
// So treat this the same as if we'd never loaded this context before (the Vacant arm below).
let value = value(entry.key())?;
let strong = std::sync::Arc::new(value);
let weak = std::sync::Arc::downgrade(&strong);
let _ = entry.insert(weak);
Ok(strong)
}
}
std::collections::btree_map::Entry::Vacant(entry) => {
// Never tried to create this value before. Load it, store the weak reference, and return the strong reference.
let value = value(entry.key())?;
let strong = std::sync::Arc::new(value);
let weak = std::sync::Arc::downgrade(&strong);
let _ = entry.insert(weak);
Ok(strong)
}
}
}