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

Returned from the read() method and grants read-only access to the enclosed data
A multi-reader, single writer lock.
Returned from the write() method and grants read-write access to the enclosed data

Enums

returned from ReadGuard::upgrade_to_write_lock()

Functions