pub struct SeqLock<L: Lock + ?Sized> { /* private fields */ }
Expand description

Exposes sequential locks backed by the kernel’s seqcount_t.

The write-side critical section is protected by a lock implementing the LockFactory trait.

Examples

use core::sync::atomic::{AtomicU32, Ordering};
use kernel::sync::{SeqLock, SpinLock};

struct Example {
    a: AtomicU32,
    b: AtomicU32,
}

fn get_sum(v: &SeqLock<SpinLock<Example>>) -> u32 {
    // Use `access` to access the fields of `Example`.
    v.access(|e| e.a.load(Ordering::Relaxed) + e.b.load(Ordering::Relaxed))
}

fn get_sum_with_guard(v: &SeqLock<SpinLock<Example>>) -> u32 {
    // Use `read` and `need_retry` in a loop to access the fields of `Example`.
    loop {
        let guard = v.read();
        let sum = guard.a.load(Ordering::Relaxed) + guard.b.load(Ordering::Relaxed);
        if !guard.need_retry() {
            break sum;
        }
    }
}

fn inc_each(v: &SeqLock<SpinLock<Example>>) {
    // Use a write-side guard to access the fields of `Example`.
    let guard = v.write();
    let a = guard.a.load(Ordering::Relaxed);
    guard.a.store(a + 1, Ordering::Relaxed);
    let b = guard.b.load(Ordering::Relaxed);
    guard.b.store(b + 1, Ordering::Relaxed);
}

Implementations

Constructs a new instance of SeqLock.

Safety

The caller must call SeqLock::init before using the seqlock.

Accesses the protected data in read mode.

Readers and writers are allowed to run concurrently, so callers must check if they need to refetch the values before they are used (e.g., because a writer changed them concurrently, rendering them potentially inconsistent). The check is performed via calls to SeqLockReadGuard::need_retry.

Accesses the protected data in read mode.

The provided closure is called repeatedly if it may have accessed inconsistent data (e.g., because a concurrent writer modified it). This is a wrapper around SeqLock::read and SeqLockReadGuard::need_retry in a loop.

Locks the underlying lock and returns a guard that allows access to the protected data.

The guard is not mutable though because readers are still allowed to concurrently access the data. The protected data structure needs to provide interior mutability itself (e.g., via atomic types) for the individual fields that can be mutated.

Trait Implementations

The type of the data protected by the lock.

The type of context, if any, that needs to be stored in the guard.

Acquires the lock, making the caller its owner.

Reacquires the lock, making the caller its owner. Read more

Releases the lock, giving up ownership of the lock. Read more

Returns the data protected by the lock.

Initialises the type instance so that it can be safely used. Read more

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

Immutably borrows from an owned value. Read more

Mutably borrows from an owned value. Read more

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

The type returned in the event of a conversion error.

Performs the conversion.

The type returned in the event of a conversion error.

Performs the conversion.