Struct lockpool::LockPool [−][src]
Expand description
This is a pool of locks where individual locks can be locked/unlocked by key. It initially considers all keys as “unlocked”, but they can be locked and if a second thread tries to acquire a lock for the same key, they will have to wait.
Under the hood, a LockPool is a HashMap of Mutexes, with some logic making sure there aren’t any race conditions when accessing the hash map.
Example:
use lockpool::LockPool;
let pool = LockPool::new();
let guard1 = pool.lock(4)?;
let guard2 = pool.lock(5)?;
// This next line would cause a deadlock or panic because `4` is already locked on this thread
// let guard3 = pool.lock(4)?;
// After dropping the corresponding guard, we can lock it again
std::mem::drop(guard1);
let guard3 = pool.lock(4)?;Implementations
Return the number of locked locks
Corner case: Poisoned locks count as locked even if they’re currently not locked
Lock a lock by key.
If the lock with this key is currently locked by a different thread, then the current thread blocks until it becomes available. Upon returning, the thread is the only thread with the lock held. A RAII guard is returned to allow scoped unlock of the lock. When the guard goes out of scope, the lock will be unlocked.
The exact behavior on locking a lock in the thread which already holds the lock is left unspecified. However, this function will not return on the second call (it might panic or deadlock, for example).
Errors
If another user of this lock panicked while holding the lock, then this call will return an error once the lock is acquired.
Panics
This function might panic when called if the lock is already held by the current thread.
Examples
use lockpool::LockPool;
let pool = LockPool::new();
let guard1 = pool.lock(4)?;
let guard2 = pool.lock(5)?;
// This next line would cause a deadlock or panic because `4` is already locked on this thread
// let guard3 = pool.lock(4)?;
// After dropping the corresponding guard, we can lock it again
std::mem::drop(guard1);
let guard3 = pool.lock(4)?;Attempts to acquire the lock with the given key.
If the lock could not be acquired at this time, then Err is returned. Otherwise, a RAII guard is returned. The lock will be unlocked when the guard is dropped.
This function does not block.
Errors
- If another user of this lock panicked while holding the lock, then this call will return TryLockError::Poisoned.
- If the lock could not be acquired because it is already locked, then this call will return TryLockError::WouldBlock.
Examples
use lockpool::{TryLockError, LockPool};
let pool = LockPool::new();
let guard1 = pool.lock(4)?;
let guard2 = pool.lock(5)?;
// This next line would cause a deadlock or panic because `4` is already locked on this thread
let guard3 = pool.try_lock(4);
assert!(matches!(guard3.unwrap_err(), TryLockError::WouldBlock));
// After dropping the corresponding guard, we can lock it again
std::mem::drop(guard1);
let guard3 = pool.lock(4)?;Unpoisons a poisoned lock.
Generally, once a thread panics while a lock is held, that lock is poisoned forever and all future attempts at locking it will return a PoisonError. This is since the resources protected by the lock are likely in an invalid state if the thread panicked while having the lock.
However, if you need an escape hatch, this function is it. Using it, you can unpoison a lock so that it can be locked again. This only works if currently no other thread is waiting for the lock.
Errors:
- Returns UnpoisonError::NotPoisoned if the lock wasn’t actually poisoned
- Returns UnpoisonError::OtherThreadsBlockedOnMutex if there are other threads currently waiting for this lock