Expand description
Allows access to some data to be serialised by a lock that does not wrap it.
In most cases, data protected by a lock is wrapped by the appropriate lock type, e.g.,
super::Mutex
or super::SpinLock
. LockedBy
is meant for cases when this is not
possible. For example, if a container has a lock and some data in the contained elements needs
to be protected by the same lock.
LockedBy
wraps the data in lieu of another locking primitive, and only allows access to it
when the caller shows evidence that ‘external’ lock is locked.
Examples
The following is an example for illustrative purposes: InnerDirectory::bytes_used
is an
aggregate of all InnerFile::bytes_used
and must be kept consistent; so we wrap InnerFile
in
a LockedBy
so that it shares a lock with InnerDirectory
. This allows us to enforce at
compile-time that access to InnerFile
is only granted when an InnerDirectory
is also
locked; we enforce at run time that the right InnerDirectory
is locked.
use kernel::sync::{LockedBy, Mutex};
struct InnerFile {
bytes_used: u64,
}
struct File {
name: String,
inner: LockedBy<InnerFile, Mutex<InnerDirectory>>,
}
struct InnerDirectory {
/// The sum of the bytes used by all files.
bytes_used: u64,
files: Vec<File>,
}
struct Directory {
name: String,
inner: Mutex<InnerDirectory>,
}
Implementations
sourceimpl<T, L: Lock + ?Sized> LockedBy<T, L>
impl<T, L: Lock + ?Sized> LockedBy<T, L>
sourcepub fn new(owner: &L, data: T) -> Self
pub fn new(owner: &L, data: T) -> Self
Constructs a new instance of LockedBy
.
It stores a raw pointer to the owner that is never dereferenced. It is only used to ensure that the right owner is being used to access the protected data. If the owner is freed, the data becomes inaccessible; if another instance of the owner is allocated on the same memory location, the data becomes accessible again: none of this affects memory safety because in any case at most one thread (or CPU) can access the protected data at a time.
sourceimpl<T: ?Sized, L: Lock + ?Sized> LockedBy<T, L>
impl<T: ?Sized, L: Lock + ?Sized> LockedBy<T, L>
sourcepub fn access<'a>(&'a self, guard: &'a Guard<'_, L>) -> &'a T
pub fn access<'a>(&'a self, guard: &'a Guard<'_, L>) -> &'a T
Returns a reference to the protected data when the caller provides evidence (via a
Guard
) that the owner is locked.
sourcepub fn access_mut<'a>(&'a self, guard: &'a mut Guard<'_, L>) -> &'a mut T
pub fn access_mut<'a>(&'a self, guard: &'a mut Guard<'_, L>) -> &'a mut T
Returns a mutable reference to the protected data when the caller provides evidence (via a
mutable Guard
) that the owner is locked mutably.
sourcepub fn access_from_mut<'a>(&'a self, owner: &'a mut L::Inner) -> &'a mut T
pub fn access_from_mut<'a>(&'a self, owner: &'a mut L::Inner) -> &'a mut T
Returns a mutable reference to the protected data when the caller provides evidence (via a mutable owner) that the owner is locked mutably. Showing a mutable reference to the owner is sufficient because we know no other references can exist to it.
Trait Implementations
impl<T: ?Sized + Send, L: Lock + ?Sized> Send for LockedBy<T, L>
impl<T: ?Sized + Send, L: Lock + ?Sized> Sync for LockedBy<T, L>
Auto Trait Implementations
impl<T, L> !RefUnwindSafe for LockedBy<T, L>
impl<T: ?Sized, L: ?Sized> Unpin for LockedBy<T, L> where
T: Unpin,
impl<T: ?Sized, L: ?Sized> UnwindSafe for LockedBy<T, L> where
T: UnwindSafe,
<L as Lock<WriteLock>>::Inner: RefUnwindSafe,
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