mirror of
https://github.com/embassy-rs/embassy.git
synced 2025-09-26 20:00:27 +00:00
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.
|
||||
//!
|
||||
//! 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.
|
||||
///
|
||||
@ -41,15 +41,50 @@ pub unsafe trait RawRwLock {
|
||||
///
|
||||
/// This read-write lock is safe to share between different executors and interrupts.
|
||||
pub struct CriticalSectionRawRwLock {
|
||||
_phantom: PhantomData<()>,
|
||||
state: RefCell<isize>,
|
||||
}
|
||||
|
||||
unsafe impl Send for CriticalSectionRawRwLock {}
|
||||
unsafe impl Sync for CriticalSectionRawRwLock {}
|
||||
|
||||
impl CriticalSectionRawRwLock {
|
||||
/// Create a new `CriticalSectionRawRwLock`.
|
||||
/// Creates a new [`CriticalSectionRawRwLock`].
|
||||
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();
|
||||
|
||||
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 {
|
||||
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.
|
||||
|
@ -350,7 +350,7 @@ where
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::blocking_rwlock::raw::NoopRawRwLock;
|
||||
use crate::rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard};
|
||||
use crate::rwlock::RwLock;
|
||||
|
||||
#[futures_test::test]
|
||||
async fn read_guard_releases_lock_when_dropped() {
|
||||
|
Loading…
x
Reference in New Issue
Block a user