fn weak_cache_get_or_insert()

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)
        }
    }
}