pub struct LockMap<K, V> { /* private fields */ }Expand description
A thread-safe hashmap that supports locking entries at the key level.
Implementations§
Source§impl<K: Eq + Hash, V> LockMap<K, V>
The main thread-safe map type providing per-key level locking.
impl<K: Eq + Hash, V> LockMap<K, V>
The main thread-safe map type providing per-key level locking.
Sourcepub fn with_capacity(capacity: usize) -> Self
pub fn with_capacity(capacity: usize) -> Self
Sourcepub fn with_capacity_and_shard_amount(
capacity: usize,
shard_amount: usize,
) -> Self
pub fn with_capacity_and_shard_amount( capacity: usize, shard_amount: usize, ) -> Self
Sourcepub fn entry(&self, key: K) -> EntryByVal<'_, K, V>where
K: Clone,
pub fn entry(&self, key: K) -> EntryByVal<'_, K, V>where
K: Clone,
Gets exclusive access to an entry in the map.
The returned EntryByVal provides exclusive access to the key and its associated value
until it is dropped.
Locking behaviour: Deadlock if called when holding the same entry.
§Examples
let map = LockMap::<String, u32>::new();
{
let mut entry = map.entry("key".to_string());
entry.insert(42);
// let _ = map.get("key".to_string()); // DEADLOCK!
// map.insert("key".to_string(), 21); // DEADLOCK!
// map.remove("key".to_string()); // DEADLOCK!
// let mut entry2 = map.entry("key".to_string()); // DEADLOCK!
}Sourcepub fn entry_by_ref<'a, 'b, Q>(
&'a self,
key: &'b Q,
) -> EntryByRef<'a, 'b, K, Q, V>
pub fn entry_by_ref<'a, 'b, Q>( &'a self, key: &'b Q, ) -> EntryByRef<'a, 'b, K, Q, V>
Gets exclusive access to an entry in the map.
The returned EntryByVal provides exclusive access to the key and its associated value
until it is dropped.
Locking behaviour: Deadlock if called when holding the same entry.
§Examples
let map = LockMap::<String, u32>::new();
{
let mut entry = map.entry_by_ref("key");
entry.insert(42);
// let _ = map.get("key"); // DEADLOCK!
// map.insert_by_ref("key", 21); // DEADLOCK!
// map.remove("key"); // DEADLOCK!
// let mut entry2 = map.entry_by_ref("key"); // DEADLOCK!
}Sourcepub fn get<Q>(&self, key: &Q) -> Option<V>
pub fn get<Q>(&self, key: &Q) -> Option<V>
Gets the value associated with the given key.
If other threads are currently accessing the key, this will wait until exclusive access is available before returning.
§Arguments
key- The key to look up
§Returns
Some(V)if the key existsNoneif the key doesn’t exist
Locking behaviour: Deadlock if called when holding the same entry.
§Examples
use lockmap::LockMap;
let map = LockMap::<String, u32>::new();
map.insert_by_ref("key", 42);
assert_eq!(map.get("key"), Some(42));
assert_eq!(map.get("missing"), None);Sourcepub fn insert(&self, key: K, value: V) -> Option<V>where
K: Clone,
pub fn insert(&self, key: K, value: V) -> Option<V>where
K: Clone,
Sets a value in the map.
If other threads are currently accessing the key, this will wait until exclusive access is available before updating.
§Arguments
key- The key to updatevalue- The value to set
Locking behaviour: Deadlock if called when holding the same entry.
§Examples
use lockmap::LockMap;
let map = LockMap::<String, u32>::new();
// Set a value
assert_eq!(map.insert("key".to_string(), 42), None);
// Update existing value
assert_eq!(map.insert("key".to_string(), 123), Some(42));Sourcepub fn insert_by_ref<Q>(&self, key: &Q, value: V) -> Option<V>
pub fn insert_by_ref<Q>(&self, key: &Q, value: V) -> Option<V>
Sets a value in the map.
If other threads are currently accessing the key, this will wait until exclusive access is available before updating.
§Arguments
key- The key to updatevalue- The value to set
Locking behaviour: Deadlock if called when holding the same entry.
§Examples
use lockmap::LockMap;
let map = LockMap::<String, u32>::new();
// Set a value
map.insert_by_ref("key", 42);
// Update existing value
map.insert_by_ref("key", 123);Sourcepub fn contains_key<Q>(&self, key: &Q) -> bool
pub fn contains_key<Q>(&self, key: &Q) -> bool
Checks if the map contains a key.
If other threads are currently accessing the key, this will wait until exclusive access is available before checking.
§Arguments
key- The key to check
§Returns
trueif the key existsfalseif the key doesn’t exist
Locking behaviour: Deadlock if called when holding the same entry.
§Examples
use lockmap::LockMap;
let map = LockMap::new();
map.insert("key", 42);
assert!(map.contains_key("key"));
assert!(!map.contains_key("non_existent_key"));Sourcepub fn remove<Q>(&self, key: &Q) -> Option<V>
pub fn remove<Q>(&self, key: &Q) -> Option<V>
Removes a key from the map.
If other threads are currently accessing the key, this will wait until exclusive access is available before removing.
§Arguments
key- The key to remove
§Returns
Some(V)if the key existsNoneif the key doesn’t exist
Locking behaviour: Deadlock if called when holding the same entry.
§Examples
use lockmap::LockMap;
let map = LockMap::<String, u32>::new();
map.insert_by_ref("key", 42);
assert_eq!(map.remove("key"), Some(42));
assert_eq!(map.get("key"), None);Sourcepub fn batch_lock<'a, M>(&'a self, keys: BTreeSet<K>) -> M
pub fn batch_lock<'a, M>(&'a self, keys: BTreeSet<K>) -> M
Acquires exclusive locks for a batch of keys in a deadlock-safe manner.
This function is designed to prevent deadlocks that can occur when multiple threads
try to acquire locks on the same set of keys in different orders. It achieves this
by taking a BTreeSet of keys, which ensures the keys are processed and locked
in a consistent, sorted order across all threads.
The function iterates through the sorted keys, acquiring an exclusive lock for each
key and its associated value. The returned Vec contains RAII guards, which
automatically release the locks when they are dropped.
§Arguments
keys- TheBTreeSetof keys to lock. The use ofBTreeSetis crucial as it enforces a global, canonical locking order, thus preventing deadlocks.
§Returns
A Vec<EntryByVal<K, V>> containing the RAII guards for each locked key.
Locking behaviour: Deadlock if called when holding the same entry.
§Examples
use lockmap::LockMap;
use std::collections::BTreeSet;
let map = LockMap::<u32, u32>::new();
map.insert(1, 100);
map.insert(2, 200);
map.insert(3, 300);
// Create a set of keys to lock. Note that the order in the set doesn't matter
// since BTreeSet will sort them.
let mut keys = BTreeSet::new();
keys.insert(3);
keys.insert(1);
keys.insert(2);
// Acquire locks for all keys in a deadlock-safe manner
let mut locked_entries = map.batch_lock::<std::collections::HashMap<_, _>>(keys);
// The locks are held as long as `locked_entries` is in scope
locked_entries.get_mut(&1).and_then(|entry| entry.insert(101));
locked_entries.get_mut(&2).and_then(|entry| entry.insert(201));
locked_entries.get_mut(&3).and_then(|entry| entry.insert(301));
// When `locked_entries` is dropped, all locks are released
drop(locked_entries);
assert_eq!(map.get(&1), Some(101));
assert_eq!(map.get(&2), Some(201));
assert_eq!(map.get(&3), Some(301));