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) -> Self where
L: LockFactory<LockedType<L::Inner> = L>,
L::Inner: Sized,
pub unsafe fn new(data: L::Inner) -> Self where
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.
Trait Implementations
sourceimpl<L: Lock + ?Sized> Lock<ReadLock> for SeqLock<L>
impl<L: Lock + ?Sized> Lock<ReadLock> for SeqLock<L>
type GuardContext = <L as Lock<WriteLock>>::GuardContext
type GuardContext = <L as Lock<WriteLock>>::GuardContext
The type of context, if any, that needs to be stored in the guard.
sourcefn lock_noguard(&self) -> L::GuardContext
fn lock_noguard(&self) -> L::GuardContext
Acquires the lock, making the caller its owner.
sourcefn relock(&self, ctx: &mut L::GuardContext)
fn relock(&self, ctx: &mut L::GuardContext)
Reacquires the lock, making the caller its owner. Read more
sourceunsafe fn unlock(&self, ctx: &mut L::GuardContext)
unsafe fn unlock(&self, ctx: &mut L::GuardContext)
Releases the lock, giving up ownership of the lock. Read more
sourcefn locked_data(&self) -> &UnsafeCell<L::Inner>
fn locked_data(&self) -> &UnsafeCell<L::Inner>
Returns the data protected by the lock.
sourceimpl<L: LockIniter + Lock + ?Sized> NeedsLockClass for SeqLock<L>
impl<L: LockIniter + Lock + ?Sized> NeedsLockClass for SeqLock<L>
sourcefn init(
self: Pin<&mut Self>,
name: &'static CStr,
key1: &'static LockClassKey,
key2: &'static LockClassKey
)
fn init(
self: Pin<&mut Self>,
name: &'static CStr,
key1: &'static LockClassKey,
key2: &'static LockClassKey
)
Initialises the type instance so that it can be safely used. Read more
impl<L: Lock + Send> Send for SeqLock<L> where
L::Inner: Send,
impl<L: Lock + Sync> Sync for SeqLock<L> where
L::Inner: Sync,
Auto Trait Implementations
impl<L> !RefUnwindSafe for SeqLock<L>
impl<L> !Unpin for SeqLock<L>
impl<L: ?Sized> UnwindSafe for SeqLock<L> where
L: UnwindSafe,
Blanket Implementations
sourceimpl<T> BorrowMut<T> for T where
T: ?Sized,
impl<T> BorrowMut<T> for T where
T: ?Sized,
const: unstable · sourcefn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more