#mutex #map #lock #rwlock #session

no-std key-mutex

Access mutexes by key

4 releases

0.1.3 Apr 6, 2024
0.1.2 Mar 18, 2024
0.1.1 Mar 18, 2024
0.1.0 Mar 18, 2024

#980 in Concurrency

MIT license

16KB
402 lines

KeyMutex

What is KeyMutex?

KeyMutex<K, V> is basically a lock-free HashMap<K, Mutex<V>> (or RwLock) with a few extra features.

Why do I need it?

Imagine you have a bunch of users identified by their IDs, and you want to have a lock for each user. That's when a KeyMutex<K, ()> comes in handy. The difference from DashMap<K, Mutex<()>> is that KeyMutex will automatically release the entry when the last mutex guard is dropped.

Things might get trickier when you want to, say, maintain a user's active sessions. You need to have a KeyMutex<K, Vec<Session>>, and you certainly don't want the entry be dropped unless the sessions are empty. Don't worry, KeyMutex handles this for you. The entry will be dropped only when Empty::is_empty returns true, which is implemented for all collections in the standard library and also, of course, for KeyMutex.


lib.rs:

A concurrent, lock-free version of HashMap<K, Mutex<V>> and HashMap<K, RwLock<V>>.

It automatically allocates mutexes and rwlocks for you, and it automatically deallocates them when they are no longer in use. The "no longer in use" condition is when the last guard is dropped AND Empty::is_empty returns true.

It's a bit like Web Locks API when V is ().

Tokio version is available behind tokio feature.

Example

use std::sync::Arc;
use key_mutex::KeyMutex;

fn main() {
    let locks = KeyMutex::<u32, BTreeSet<String>>::new();
    let mut lock = locks.lock(1).unwrap();
    lock.insert("Hello".to_owned());
    lock.insert("World".to_owned());
    drop(lock);

    // Value is not empty and thus is not dropped
    assert_eq!(locks.len(), 1);

    let mut lock = locks.lock(1).unwrap();
    assert_eq!(lock.len(), 2);
    lock.clear();
    drop(lock);

    // Should be dropped now
    assert_eq!(locks.len(), 0);
}

Dependencies

~1–6.5MB
~41K SLoC