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
sourceimpl<L: Lock> SeqLock<L>
impl<L: Lock> SeqLock<L>
sourcepub unsafe fn new(data: L::Inner) -> Selfwhere
L: LockFactory<LockedType<L::Inner> = L>,
L::Inner: Sized,
pub unsafe fn new(data: L::Inner) -> Selfwhere
L: LockFactory<LockedType<L::Inner> = L>,
L::Inner: Sized,
Constructs a new instance of SeqLock
.
Safety
The caller must call SeqLock::init
before using the seqlock.
sourceimpl<L: Lock + ?Sized> SeqLock<L>
impl<L: Lock + ?Sized> SeqLock<L>
sourcepub fn read(&self) -> SeqLockReadGuard<'_, L>
pub fn read(&self) -> SeqLockReadGuard<'_, L>
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
.
sourcepub fn access<F: Fn(&L::Inner) -> R, R>(&self, cb: F) -> R
pub fn access<F: Fn(&L::Inner) -> R, R>(&self, cb: F) -> R
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.
sourcepub fn write(&self) -> Guard<'_, Self, ReadLock>
pub fn write(&self) -> Guard<'_, Self, ReadLock>
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.