10 releases
0.1.1 | Nov 8, 2024 |
---|---|
0.1.0 | Nov 8, 2024 |
0.0.8 | Jan 25, 2024 |
0.0.7 | Dec 15, 2023 |
0.0.2 | Apr 11, 2022 |
#68 in Concurrency
5,083 downloads per month
Used in tonbo
340KB
4.5K
SLoC
lockable
The lockable library offers thread-safe HashMap (see LockableHashMap), LruCache (see LockableLruCache) and LockPool (see LockPool) types. In all of these dat atypes, individual keys can be locked/unlocked, even if there is no entry for this key in the map or cache.
This can be very useful for synchronizing access to an underlying key-value store or for building cache data structures on top of such a key-value store.
LRU cache example
This example builds a simple LRU cache and locks some entries.
use lockable::{AsyncLimit, LockableLruCache};
let lockable_cache = LockableLruCache::<i64, String>::new();
// Insert an entry
lockable_cache.async_lock(4, AsyncLimit::no_limit())
.await?
.insert(String::from("Value"));
// Hold a lock on a different entry
let guard = lockable_cache.async_lock(5, AsyncLimit::no_limit())
.await?;
// This next line would wait until the lock gets released,
// which in this case would cause a deadlock because we're
// on the same thread
// let guard2 = lockable_cache.async_lock(5, AsyncLimit::no_limit())
// .await?;
// After dropping the corresponding guard, we can lock it again
std::mem::drop(guard);
let guard2 = lockable_cache.async_lock(5, AsyncLimit::no_limit())
.await?;
Lockpool example
This example builds a simple lock pool using the LockPool data structure. A lock pool is a pool of keyable locks. This can be used if you don't need a cache but just some way to synchronize access to an underlying resource.
use lockable::LockPool;
let lockpool = LockPool::new();
let guard1 = lockpool.async_lock(4).await;
let guard2 = lockpool.async_lock(5).await;
// This next line would wait until the lock gets released,
// which in this case would cause a deadlock because we're
// on the same thread.
// let guard3 = lockpool.async_lock(4).await;
// After dropping the corresponding guard, we can lock it again
std::mem::drop(guard1);
let guard3 = lockpool.async_lock(4).await;
HashMap example
If you need a lockable key-value store but don't need the LRU ordering, you can use LockableHashMap.
use lockable::{AsyncLimit, LockableHashMap};
let lockable_map = LockableHashMap::<i64, String>::new();
// Insert an entry
lockable_map.async_lock(4, AsyncLimit::no_limit())
.await?
.insert(String::from("Value"));
// Hold a lock on a different entry
let guard = lockable_map.async_lock(5, AsyncLimit::no_limit())
.await?;
// This next line would wait until the lock gets released,
// which in this case would cause a deadlock because we're
// on the same thread
// let guard2 = lockable_map.async_lock(5, AsyncLimit::no_limit())
// .await?;
// After dropping the corresponding guard, we can lock it again
std::mem::drop(guard);
let guard2 = lockable_map.async_lock(5, AsyncLimit::no_limit())
.await?;
Crate Features
lru
: Enables the LockableLruCache type which adds a dependency on the lru crate.
License: MIT OR Apache-2.0
Dependencies
~4–10MB
~103K SLoC