glock

Granular locking crate for Rust. Instead of using coarse-grained Mutex or RwLock which can be used to lock an entire structure, glock provides more granular locking.

GLock can be either nested or non-nested. The same locking rules apply in both cases, but the way they are constructed is different in each case.

Nested GLocks

When GLocks are nested (i.e. child GLocks are protected inside parent GLock), a GLockBuilder must be used to construct the parent GLock.

Example

``` extern crate glock;

use glock::*;

struct Parent { a: GLock, b: GLock, }

struct Child { x: GLock, y: GLock, }

fn main() { // Construct parent GLocks and all of its nested GLocks let parentlock = { // Prepare parent builder let parentbuilder = GLock::::newrootbuilder();

    // Build child GLock protecting first Child struct
    let child1_lock = {
        let child1_builder = parent_builder.new_child_builder().unwrap();

        let child1 = Child {
            x: child1_builder.new_child(0i32).unwrap(),
            y: child1_builder.new_child(0i32).unwrap(),
        };

        child1_builder.build(child1).unwrap()
    };

    // Build child GLock protecting second Child struct
    let child2_lock = {
        let child2_builder = parent_builder.new_child_builder().unwrap();

        let child2 = Child {
            x: child2_builder.new_child(0i32).unwrap(),
            y: child2_builder.new_child(0i32).unwrap(),
        };

        child2_builder.build(child2).unwrap()
    };

    // Create parent struct
    let parent = Parent {
        a: child1_lock,
        b: child2_lock,
    };

    // Build parent GLock protecting parent struct
    parent_builder.build(parent).unwrap()
};

// Lock parent
let p_guard = parent_lock.lock(LockType::IntentionExclusive).unwrap();

// Lock first child
let a_guard = p_guard.a.lock_using_parent(LockType::IntentionExclusive, &p_guard).unwrap();

// Lock and modify field x inside first child
let mut a_x_guard = a_guard.x.lock_exclusive_using_parent(&a_guard).unwrap();
*a_x_guard = 10;

// Lock and modify field y inside first child
let mut a_y_guard = a_guard.y.lock_exclusive_using_parent(&a_guard).unwrap();
*a_y_guard = 20;

// This one will fail with LockError::LockBusy
let p_guard_2 = parent_lock.try_lock(LockType::Shared).unwrap();

} ```

Non-Nested GLocks

When GLocks are not nested, you can access child locks directly. If you try to acquire a child GLock without locking its parent first, an implicit lock will be acquired on its parent and released when the child GLockGuard is dropped.

Example

``` extern crate glock;

use glock::*;

fn main() { // Create parent lock let parentlock = GLock::newroot(0u32).unwrap();

// Create child locks
let child1_lock = parent_lock.new_child(0u32).unwrap();
let child2_lock = parent_lock.new_child(0u32).unwrap();

// An implicit IntentionExclusive lock is acquired on parent_lock,
// Because child1_lock is a child of parent_lock.
let mut child1_guard = child1_lock.lock_exclusive().unwrap();
*child1_guard = 10;

// This will fail with LockError::LockBusy because an IntentionExclusive lock is held
// on parent_lock
let parent_guard2 = parent_lock.try_lock(LockType::Shared).unwrap();

} ```