Crate widerwlock
source ·Expand description
Wide (Partitioned) Read Write Lock
This crate implements an enterprise-grade read-write lock, typically used for large data structures.
The lock is internally 8x partitioned, which allows it to scale much better with a large number of readers,
as compared to std::sync::RwLock
.
Even though this is a large lock, it has better performance characteristic for uncontended single reader
or single writer lock than std::sync::RwLock
.
The lock uses a contiguous 576 byte heap area to store its state, so it’s not a light-weight lock.
If you have a complex data structure that holds a GB of data, this would be an appropriate lock.
An interesting feature of this lock, beside its performance, is its Read->Write upgrade mechanics. The ReadGuard
allows an
upgrade to a write-lock and informs the user whether the upgrade succeeded atomically or not. This enables
the following pattern:
- Read to see if the data structure is in a particular state (e.g. contains a value).
- if not, upgrade to a write lock
- if upgrade was not atomic, perform the (potentially expensive) read again
- write to the structure if needed
Here is an example:
use widerwlock::*;
use std::collections::HashMap;
use std::hash::Hash;
struct RwMap<K,V> {
map: WideRwLock<HashMap<K,V>>,
}
impl<K: Eq + Hash,V> RwMap<K, V> {
pub fn insert_if_absent<F>(&self, key: K, v_factory: F)
where F: FnOnce(&K) -> V {
let guard: ReadGuard<_> = self.map.read();
if !guard.contains_key(&key) { // perform the read.
let result: UpgradeResult<_> = guard.upgrade_to_write_lock();
let atomic = result.atomic();
// the atomic return ensures the (potentially) expensive double read
// can be avoided when atomic
let mut write_guard: WriteGuard<_> = result.into_guard();
if !atomic {
// we have to check again, because another writer may have come in
if write_guard.contains_key(&key) { return; }
}
let v = v_factory(&key);
write_guard.insert(key, v);
}
}
}
Structs
read()
method and grants read-only access to the enclosed datawrite()
method and grants read-write access to the enclosed dataEnums
ReadGuard::upgrade_to_write_lock()