feat: rwlock instead of mutex for global scope
* Rwlock -> InnerRwLock * RwLock makes use of InnerRwLock. Signed-off-by: Anhad Singh <andypython@protonmail.com>
This commit is contained in:
+124
-3
@@ -1,8 +1,13 @@
|
||||
use core::sync::atomic::{AtomicU32, Ordering};
|
||||
use core::{
|
||||
cell::UnsafeCell,
|
||||
fmt, ops,
|
||||
ptr::NonNull,
|
||||
sync::atomic::{AtomicU32, Ordering},
|
||||
};
|
||||
|
||||
use crate::{header::time::timespec, pthread::Pshared};
|
||||
|
||||
pub struct Rwlock {
|
||||
pub struct InnerRwLock {
|
||||
state: AtomicU32,
|
||||
}
|
||||
// PTHREAD_RWLOCK_INITIALIZER is defined as "all zeroes".
|
||||
@@ -15,7 +20,7 @@ const EXCLUSIVE: u32 = COUNT_MASK;
|
||||
// supporting timeouts.
|
||||
// TODO: Add futex ops that use bitmasks.
|
||||
|
||||
impl Rwlock {
|
||||
impl InnerRwLock {
|
||||
pub const fn new(_pshared: Pshared) -> Self {
|
||||
Self {
|
||||
state: AtomicU32::new(0),
|
||||
@@ -143,3 +148,119 @@ impl Rwlock {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct RwLock<T: ?Sized> {
|
||||
inner: InnerRwLock,
|
||||
data: UnsafeCell<T>,
|
||||
}
|
||||
|
||||
unsafe impl<T: ?Sized + Send> Send for RwLock<T> {}
|
||||
unsafe impl<T: ?Sized + Send + Sync> Sync for RwLock<T> {}
|
||||
|
||||
impl<T> RwLock<T> {
|
||||
pub const fn new(val: T) -> Self {
|
||||
Self {
|
||||
inner: InnerRwLock::new(Pshared::Private),
|
||||
data: UnsafeCell::new(val),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized> RwLock<T> {
|
||||
pub fn read(&self) -> ReadGuard<'_, T> {
|
||||
self.inner.acquire_read_lock(None);
|
||||
unsafe { ReadGuard::new(self) }
|
||||
}
|
||||
|
||||
pub fn write(&self) -> WriteGuard<'_, T> {
|
||||
self.inner.acquire_write_lock(None);
|
||||
unsafe { WriteGuard::new(self) }
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ReadGuard<'a, T: ?Sized + 'a> {
|
||||
lock: &'a RwLock<T>,
|
||||
}
|
||||
|
||||
impl<T: ?Sized> !Send for ReadGuard<'_, T> {}
|
||||
unsafe impl<T: ?Sized + Sync> Sync for ReadGuard<'_, T> {}
|
||||
|
||||
impl<'a, T: ?Sized> ReadGuard<'a, T> {
|
||||
unsafe fn new(lock: &'a RwLock<T>) -> Self {
|
||||
Self { lock }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: ?Sized> ops::Deref for ReadGuard<'a, T> {
|
||||
type Target = T;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
// SAFETY: We have shared reference to the data.
|
||||
unsafe { &*self.lock.data.get() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: ?Sized> Drop for ReadGuard<'a, T> {
|
||||
fn drop(&mut self) {
|
||||
self.lock.inner.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: ?Sized + fmt::Debug> fmt::Debug for ReadGuard<'a, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Debug::fmt(&**self, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: ?Sized + fmt::Display> fmt::Display for ReadGuard<'a, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Display::fmt(&**self, f)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct WriteGuard<'a, T: ?Sized + 'a> {
|
||||
lock: &'a RwLock<T>,
|
||||
}
|
||||
|
||||
impl<T: ?Sized> !Send for WriteGuard<'_, T> {}
|
||||
unsafe impl<T: ?Sized + Sync> Sync for WriteGuard<'_, T> {}
|
||||
|
||||
impl<'a, T: ?Sized> WriteGuard<'a, T> {
|
||||
unsafe fn new(lock: &'a RwLock<T>) -> Self {
|
||||
Self { lock }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: ?Sized> ops::Deref for WriteGuard<'a, T> {
|
||||
type Target = T;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
// SAFETY: We have exclusive reference to the data.
|
||||
unsafe { &*self.lock.data.get() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: ?Sized> ops::DerefMut for WriteGuard<'a, T> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
// SAFETY: We have exclusive reference to the data.
|
||||
unsafe { &mut *self.lock.data.get() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: ?Sized> Drop for WriteGuard<'a, T> {
|
||||
fn drop(&mut self) {
|
||||
self.lock.inner.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: ?Sized + fmt::Debug> fmt::Debug for WriteGuard<'a, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Debug::fmt(&**self, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: ?Sized + fmt::Display> fmt::Display for WriteGuard<'a, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Display::fmt(&**self, f)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user