mirror of
https://github.com/embassy-rs/embassy.git
synced 2025-10-02 06:40:32 +00:00
Add RawRwLock
trait and RawRwLockImpl
struct implementation
* Implement `RawRwLock` trait with methods for read and write locking * Implement `RawRwLockImpl` struct with atomic state and waker * Implement `RawRwLockImpl::lock_read`, `RawRwLockImpl::try_lock_read`, and `RawRwLockImpl::unlock_read` methods * Implement `RawRwLockImpl::lock_write`, `RawRwLockImpl::try_lock_write`, and `RawRwLockImpl::unlock_write` methods
This commit is contained in:
parent
6904b0cc64
commit
114cfdd86b
86
embassy-sync/src/blocking_mutex/raw_rwlock.rs
Normal file
86
embassy-sync/src/blocking_mutex/raw_rwlock.rs
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
use core::sync::atomic::{AtomicUsize, Ordering};
|
||||||
|
use core::task::Waker;
|
||||||
|
use core::cell::UnsafeCell;
|
||||||
|
|
||||||
|
pub trait RawRwLock {
|
||||||
|
fn lock_read(&self);
|
||||||
|
fn try_lock_read(&self) -> bool;
|
||||||
|
fn unlock_read(&self);
|
||||||
|
fn lock_write(&self);
|
||||||
|
fn try_lock_write(&self) -> bool;
|
||||||
|
fn unlock_write(&self);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct RawRwLockImpl {
|
||||||
|
state: AtomicUsize,
|
||||||
|
waker: UnsafeCell<Option<Waker>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RawRwLockImpl {
|
||||||
|
pub const fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
state: AtomicUsize::new(0),
|
||||||
|
waker: UnsafeCell::new(None),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl Send for RawRwLockImpl {}
|
||||||
|
unsafe impl Sync for RawRwLockImpl {}
|
||||||
|
|
||||||
|
impl RawRwLock for RawRwLockImpl {
|
||||||
|
fn lock_read(&self) {
|
||||||
|
loop {
|
||||||
|
let state = self.state.load(Ordering::Acquire);
|
||||||
|
if state & 1 == 0 {
|
||||||
|
if self.state.compare_and_swap(state, state + 2, Ordering::AcqRel) == state {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn try_lock_read(&self) -> bool {
|
||||||
|
let state = self.state.load(Ordering::Acquire);
|
||||||
|
if state & 1 == 0 {
|
||||||
|
if self.state.compare_and_swap(state, state + 2, Ordering::AcqRel) == state {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unlock_read(&self) {
|
||||||
|
self.state.fetch_sub(2, Ordering::Release);
|
||||||
|
if self.state.load(Ordering::Acquire) == 0 {
|
||||||
|
if let Some(waker) = unsafe { &*self.waker.get() } {
|
||||||
|
waker.wake_by_ref();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lock_write(&self) {
|
||||||
|
loop {
|
||||||
|
let state = self.state.load(Ordering::Acquire);
|
||||||
|
if state == 0 {
|
||||||
|
if self.state.compare_and_swap(0, 1, Ordering::AcqRel) == 0 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn try_lock_write(&self) -> bool {
|
||||||
|
if self.state.compare_and_swap(0, 1, Ordering::AcqRel) == 0 {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unlock_write(&self) {
|
||||||
|
self.state.store(0, Ordering::Release);
|
||||||
|
if let Some(waker) = unsafe { &*self.waker.get() } {
|
||||||
|
waker.wake_by_ref();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,86 +0,0 @@
|
|||||||
use core::sync::atomic::{AtomicUsize, Ordering};
|
|
||||||
use core::task::Waker;
|
|
||||||
use core::cell::UnsafeCell;
|
|
||||||
|
|
||||||
pub trait RawRwLock {
|
|
||||||
fn lock_read(&self);
|
|
||||||
fn try_lock_read(&self) -> bool;
|
|
||||||
fn unlock_read(&self);
|
|
||||||
fn lock_write(&self);
|
|
||||||
fn try_lock_write(&self) -> bool;
|
|
||||||
fn unlock_write(&self);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct RawRwLockImpl {
|
|
||||||
state: AtomicUsize,
|
|
||||||
waker: UnsafeCell<Option<Waker>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl RawRwLockImpl {
|
|
||||||
pub const fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
state: AtomicUsize::new(0),
|
|
||||||
waker: UnsafeCell::new(None),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe impl Send for RawRwLockImpl {}
|
|
||||||
unsafe impl Sync for RawRwLockImpl {}
|
|
||||||
|
|
||||||
impl RawRwLock for RawRwLockImpl {
|
|
||||||
fn lock_read(&self) {
|
|
||||||
loop {
|
|
||||||
let state = self.state.load(Ordering::Acquire);
|
|
||||||
if state & 1 == 0 {
|
|
||||||
if self.state.compare_and_swap(state, state + 2, Ordering::AcqRel) == state {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn try_lock_read(&self) -> bool {
|
|
||||||
let state = self.state.load(Ordering::Acquire);
|
|
||||||
if state & 1 == 0 {
|
|
||||||
if self.state.compare_and_swap(state, state + 2, Ordering::AcqRel) == state {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
fn unlock_read(&self) {
|
|
||||||
self.state.fetch_sub(2, Ordering::Release);
|
|
||||||
if self.state.load(Ordering::Acquire) == 0 {
|
|
||||||
if let Some(waker) = unsafe { &*self.waker.get() } {
|
|
||||||
waker.wake_by_ref();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn lock_write(&self) {
|
|
||||||
loop {
|
|
||||||
let state = self.state.load(Ordering::Acquire);
|
|
||||||
if state == 0 {
|
|
||||||
if self.state.compare_and_swap(0, 1, Ordering::AcqRel) == 0 {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn try_lock_write(&self) -> bool {
|
|
||||||
if self.state.compare_and_swap(0, 1, Ordering::AcqRel) == 0 {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
fn unlock_write(&self) {
|
|
||||||
self.state.store(0, Ordering::Release);
|
|
||||||
if let Some(waker) = unsafe { &*self.waker.get() } {
|
|
||||||
waker.wake_by_ref();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user