Add async mutex first version
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
Signed-off-by: Julien CLEMENT <julien.clement@epita.fr>
This commit is contained in:
parent
0c0af6414e
commit
af9a7aa712
@ -19,8 +19,6 @@ use drivers::vga::{self, Color, ColorCode};
|
||||
use multiboot2::BootInformation;
|
||||
use task::{executor::Executor, keyboard, Task};
|
||||
|
||||
use fs::iso::iso9660::{IsoDir, IsoPrimVolDesc, MultiEndian32};
|
||||
|
||||
#[alloc_error_handler]
|
||||
fn alloc_error_handler(layout: alloc::alloc::Layout) -> ! {
|
||||
panic!("Allocation error: {:?}", layout)
|
||||
|
@ -1,3 +1,5 @@
|
||||
pub mod serialize;
|
||||
pub mod mutex;
|
||||
|
||||
pub use serialize::unserialize;
|
||||
pub use mutex::AsyncMutex;
|
111
src/utils/mutex.rs
Normal file
111
src/utils/mutex.rs
Normal file
@ -0,0 +1,111 @@
|
||||
use core::future::Future;
|
||||
use core::pin::Pin;
|
||||
use core::cell::UnsafeCell;
|
||||
use core::ops::{Deref, DerefMut, Drop};
|
||||
use core::sync::atomic::{AtomicBool, Ordering};
|
||||
use core::task::{Context, Poll};
|
||||
use alloc::rc::Rc;
|
||||
|
||||
use futures_util::task::AtomicWaker;
|
||||
|
||||
#[derive(Clone)]
|
||||
struct Lock {
|
||||
lock: Rc<AtomicBool>,
|
||||
waker: Rc<AtomicWaker>,
|
||||
}
|
||||
|
||||
pub struct AsyncMutex<T> {
|
||||
lock: Lock,
|
||||
inner: UnsafeCell<T>,
|
||||
}
|
||||
|
||||
pub struct AsyncMutexGuard<'a, T>
|
||||
where
|
||||
T: 'a,
|
||||
{
|
||||
mutex: &'a AsyncMutex<T>
|
||||
}
|
||||
|
||||
impl Lock {
|
||||
fn new() -> Self {
|
||||
Lock {
|
||||
lock: Rc::new(AtomicBool::new(false)),
|
||||
waker: Rc::new(AtomicWaker::new()),
|
||||
}
|
||||
}
|
||||
|
||||
fn try_lock(&self) -> bool {
|
||||
self.lock.swap(true, Ordering::Acquire)
|
||||
}
|
||||
|
||||
fn drop(&self) {
|
||||
self.lock.swap(false, Ordering::Release);
|
||||
self.waker.wake();
|
||||
}
|
||||
}
|
||||
|
||||
impl Future for Lock {
|
||||
type Output = ();
|
||||
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
|
||||
if self.try_lock() {
|
||||
return Poll::Ready(());
|
||||
}
|
||||
|
||||
self.waker.register(&cx.waker());
|
||||
|
||||
match self.try_lock() {
|
||||
true => {
|
||||
self.waker.take();
|
||||
Poll::Ready(())
|
||||
},
|
||||
false => Poll::Pending,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> AsyncMutex<T> {
|
||||
pub fn new(val: T) -> Self {
|
||||
AsyncMutex {
|
||||
lock: Lock::new(),
|
||||
inner: UnsafeCell::new(val),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn try_lock(&self) -> Option<AsyncMutexGuard<T>> {
|
||||
if self.lock.try_lock() {
|
||||
Some(AsyncMutexGuard { mutex: self })
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn lock(&self) -> AsyncMutexGuard<'_, T> {
|
||||
self.lock.clone().await;
|
||||
AsyncMutexGuard { mutex: self }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl<T> Drop for AsyncMutexGuard<'_, T> {
|
||||
fn drop(&mut self) {
|
||||
self.mutex.lock.drop();
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Deref for AsyncMutexGuard<'_, T> {
|
||||
type Target = T;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
unsafe {
|
||||
&*self.mutex.inner.get()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> DerefMut for AsyncMutexGuard<'_, T> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
unsafe {
|
||||
&mut *self.mutex.inner.get()
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user