Implement read-write lock methods in CriticalSectionRawRwLock and update tests
This commit is contained in:
parent
5568478225
commit
9cbdc9f11d
@ -1,7 +1,7 @@
|
|||||||
//! Read-Write Lock primitives.
|
//! Read-Write Lock primitives.
|
||||||
//!
|
//!
|
||||||
//! This module provides a trait for read-write locks that can be used in different contexts.
|
//! This module provides a trait for read-write locks that can be used in different contexts.
|
||||||
use core::marker::PhantomData;
|
use core::{cell::RefCell, marker::PhantomData};
|
||||||
|
|
||||||
/// Raw read-write lock trait.
|
/// Raw read-write lock trait.
|
||||||
///
|
///
|
||||||
@ -41,15 +41,50 @@ pub unsafe trait RawRwLock {
|
|||||||
///
|
///
|
||||||
/// This read-write lock is safe to share between different executors and interrupts.
|
/// This read-write lock is safe to share between different executors and interrupts.
|
||||||
pub struct CriticalSectionRawRwLock {
|
pub struct CriticalSectionRawRwLock {
|
||||||
_phantom: PhantomData<()>,
|
state: RefCell<isize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl Send for CriticalSectionRawRwLock {}
|
unsafe impl Send for CriticalSectionRawRwLock {}
|
||||||
unsafe impl Sync for CriticalSectionRawRwLock {}
|
unsafe impl Sync for CriticalSectionRawRwLock {}
|
||||||
|
|
||||||
impl CriticalSectionRawRwLock {
|
impl CriticalSectionRawRwLock {
|
||||||
/// Create a new `CriticalSectionRawRwLock`.
|
/// Creates a new [`CriticalSectionRawRwLock`].
|
||||||
pub const fn new() -> Self {
|
pub const fn new() -> Self {
|
||||||
Self { _phantom: PhantomData }
|
Self { state: RefCell::new(0) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lock_read(&self) {
|
||||||
|
critical_section::with(|_| {
|
||||||
|
let mut state = self.state.borrow_mut();
|
||||||
|
|
||||||
|
while *state & WRITER != 0 {
|
||||||
|
// Spin until the writer releases the lock
|
||||||
|
}
|
||||||
|
*state += 1;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unlock_read(&self) {
|
||||||
|
critical_section::with(|_| {
|
||||||
|
*self.state.borrow_mut() -= 1;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lock_write(&self) {
|
||||||
|
critical_section::with(|_| {
|
||||||
|
let mut state = self.state.borrow_mut();
|
||||||
|
|
||||||
|
while *state != 0 {
|
||||||
|
// Spin until all readers and writers release the lock
|
||||||
|
}
|
||||||
|
*state = WRITER;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unlock_write(&self) {
|
||||||
|
critical_section::with(|_| {
|
||||||
|
*self.state.borrow_mut() = 0;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,14 +92,24 @@ unsafe impl RawRwLock for CriticalSectionRawRwLock {
|
|||||||
const INIT: Self = Self::new();
|
const INIT: Self = Self::new();
|
||||||
|
|
||||||
fn read_lock<R>(&self, f: impl FnOnce() -> R) -> R {
|
fn read_lock<R>(&self, f: impl FnOnce() -> R) -> R {
|
||||||
critical_section::with(|_| f())
|
self.lock_read();
|
||||||
|
let result = f();
|
||||||
|
self.unlock_read();
|
||||||
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_lock<R>(&self, f: impl FnOnce() -> R) -> R {
|
fn write_lock<R>(&self, f: impl FnOnce() -> R) -> R {
|
||||||
critical_section::with(|_| f())
|
self.lock_write();
|
||||||
|
let result = f();
|
||||||
|
self.unlock_write();
|
||||||
|
result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const WRITER: isize = -1;
|
||||||
|
|
||||||
|
// The rest of the file remains unchanged
|
||||||
|
|
||||||
// ================
|
// ================
|
||||||
|
|
||||||
/// A read-write lock that allows borrowing data in the context of a single executor.
|
/// A read-write lock that allows borrowing data in the context of a single executor.
|
||||||
|
|||||||
@ -350,7 +350,7 @@ where
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::blocking_rwlock::raw::NoopRawRwLock;
|
use crate::blocking_rwlock::raw::NoopRawRwLock;
|
||||||
use crate::rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard};
|
use crate::rwlock::RwLock;
|
||||||
|
|
||||||
#[futures_test::test]
|
#[futures_test::test]
|
||||||
async fn read_guard_releases_lock_when_dropped() {
|
async fn read_guard_releases_lock_when_dropped() {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user