1
0
Fork 0
forked from wry/wry

autocommit 2022-01-08 23:04:44 CET

This commit is contained in:
Julian Orth 2022-01-08 23:04:44 +01:00
parent 3336f1ab6a
commit 4efb187e24
3 changed files with 109 additions and 64 deletions

View file

@ -171,6 +171,9 @@ mod timeout {
mod task { mod task {
use crate::async_engine::queue::DispatchQueue; use crate::async_engine::queue::DispatchQueue;
use crate::utils::ptr_ext::{MutPtrExt, PtrExt};
use crate::NumCell;
use std::cell::{Cell, UnsafeCell};
use std::future::Future; use std::future::Future;
use std::mem::ManuallyDrop; use std::mem::ManuallyDrop;
use std::pin::Pin; use std::pin::Pin;
@ -208,25 +211,27 @@ mod task {
}; };
unsafe fn poll(data: *mut u8, ctx: &mut Context<'_>) -> Poll<T> { unsafe fn poll(data: *mut u8, ctx: &mut Context<'_>) -> Poll<T> {
let task = &mut *(data as *mut Task<T, F>); let task = (data as *const Task<T, F>).deref();
if task.state & COMPLETED == 0 { if &task.state & COMPLETED == 0 {
task.waker = Some(ctx.waker().clone()); task.waker.set(Some(ctx.waker().clone()));
Poll::Pending Poll::Pending
} else if task.state & EMPTIED == 0 { } else if &task.state & EMPTIED == 0 {
task.state |= EMPTIED; task.state.or_assign(EMPTIED);
Poll::Ready(ptr::read(&*task.data.result)) Poll::Ready(ptr::read(&*task.data.get().deref().result))
} else { } else {
panic!("Future polled after it has already been emptied"); panic!("Future polled after it has already been emptied");
} }
} }
unsafe fn drop(data: *mut u8) { unsafe fn drop(data: *mut u8) {
let task = &mut *(data as *mut Task<T, F>); {
task.state |= CANCELLED; let task = (data as *const Task<T, F>).deref();
if task.state & RUNNING == 0 { task.state.or_assign(CANCELLED);
task.drop_data(); if &task.state & RUNNING == 0 {
task.drop_data();
}
} }
task.dec_ref_count(); Task::<T, F>::dec_ref_count(data as _);
} }
} }
@ -240,23 +245,23 @@ mod task {
future: ManuallyDrop<F>, future: ManuallyDrop<F>,
} }
const RUNNING: usize = 1; const RUNNING: u32 = 1;
const RUN_AGAIN: usize = 2; const RUN_AGAIN: u32 = 2;
const COMPLETED: usize = 4; const COMPLETED: u32 = 4;
const EMPTIED: usize = 8; const EMPTIED: u32 = 8;
const CANCELLED: usize = 16; const CANCELLED: u32 = 16;
struct Task<T, F: Future<Output = T>> { struct Task<T, F: Future<Output = T>> {
ref_count: u64, ref_count: NumCell<u64>,
state: usize, state: NumCell<u32>,
data: TaskData<T, F>, data: UnsafeCell<TaskData<T, F>>,
waker: Option<Waker>, waker: Cell<Option<Waker>>,
queue: Rc<DispatchQueue>, queue: Rc<DispatchQueue>,
} }
pub(super) struct Runnable { pub(super) struct Runnable {
data: *mut u8, data: *const u8,
run: unsafe fn(data: *mut u8, run: bool), run: unsafe fn(data: *const u8, run: bool),
} }
impl Runnable { impl Runnable {
@ -278,13 +283,13 @@ mod task {
impl DispatchQueue { impl DispatchQueue {
pub(super) fn spawn<T, F: Future<Output = T>>(self: &Rc<Self>, f: F) -> SpawnedFuture<T> { pub(super) fn spawn<T, F: Future<Output = T>>(self: &Rc<Self>, f: F) -> SpawnedFuture<T> {
let mut f = Box::new(Task { let f = Box::new(Task {
ref_count: 1, ref_count: NumCell::new(1),
state: 0, state: NumCell::new(0),
data: TaskData { data: UnsafeCell::new(TaskData {
future: ManuallyDrop::new(f), future: ManuallyDrop::new(f),
}, }),
waker: None, waker: Cell::new(None),
queue: self.clone(), queue: self.clone(),
}); });
unsafe { unsafe {
@ -306,23 +311,22 @@ mod task {
Self::waker_drop, Self::waker_drop,
); );
unsafe fn run_proxy(data: *mut u8, run: bool) { unsafe fn run_proxy(data: *const u8, run: bool) {
let task = &mut *(data as *mut Self); let task = data as *const Self;
if run { if run {
task.run(); task.deref().run();
} }
task.dec_ref_count(); Self::dec_ref_count(task);
} }
unsafe fn dec_ref_count(&mut self) { unsafe fn dec_ref_count(slf: *const Self) {
self.ref_count -= 1; if slf.deref().ref_count.fetch_sub(1) == 1 {
if self.ref_count == 0 { Box::from_raw(slf as *mut Self);
Box::from_raw(self);
} }
} }
unsafe fn inc_ref_count(&mut self) { unsafe fn inc_ref_count(&self) {
self.ref_count += 1; self.ref_count.fetch_add(1);
} }
unsafe fn waker_clone(data: *const ()) -> RawWaker { unsafe fn waker_clone(data: *const ()) -> RawWaker {
@ -337,63 +341,62 @@ mod task {
} }
unsafe fn waker_wake_by_ref(data: *const ()) { unsafe fn waker_wake_by_ref(data: *const ()) {
let task = &mut *(data as *mut Self); (data as *const Self).deref().schedule_run();
task.schedule_run();
} }
unsafe fn waker_drop(data: *const ()) { unsafe fn waker_drop(data: *const ()) {
let task = &mut *(data as *mut Self); Self::dec_ref_count(data as _)
task.dec_ref_count();
} }
unsafe fn schedule_run(&mut self) { unsafe fn schedule_run(&self) {
if self.state & (COMPLETED | CANCELLED) == 0 { if &self.state & (COMPLETED | CANCELLED) == 0 {
if self.state & RUNNING == 0 { if &self.state & RUNNING == 0 {
self.state |= RUNNING; self.state.or_assign(RUNNING);
self.inc_ref_count(); self.inc_ref_count();
let data = self as *mut _ as _; let data = self as *const _ as _;
self.queue.push(Runnable { self.queue.push(Runnable {
data, data,
run: Self::run_proxy, run: Self::run_proxy,
}); });
} else { } else {
self.state |= RUN_AGAIN; self.state.or_assign(RUN_AGAIN);
} }
} }
} }
unsafe fn run(&mut self) { unsafe fn run(&self) {
if self.state & CANCELLED == 0 { if &self.state & CANCELLED == 0 {
let data = self.data.get().deref_mut();
self.inc_ref_count(); self.inc_ref_count();
let raw_waker = RawWaker::new(self as *const _ as _, Self::VTABLE); let raw_waker = RawWaker::new(self as *const _ as _, Self::VTABLE);
let waker = Waker::from_raw(raw_waker); let waker = Waker::from_raw(raw_waker);
let mut ctx = Context::from_waker(&waker); let mut ctx = Context::from_waker(&waker);
if let Poll::Ready(d) = Pin::new_unchecked(&mut *self.data.future).poll(&mut ctx) { if let Poll::Ready(d) = Pin::new_unchecked(&mut *data.future).poll(&mut ctx) {
ManuallyDrop::drop(&mut self.data.future); ManuallyDrop::drop(&mut data.future);
ptr::write(&mut self.data.result, ManuallyDrop::new(d)); ptr::write(&mut data.result, ManuallyDrop::new(d));
self.state |= COMPLETED; self.state.or_assign(COMPLETED);
if let Some(waker) = self.waker.take() { if let Some(waker) = self.waker.take() {
waker.wake(); waker.wake();
} }
} }
} }
self.state &= !RUNNING; self.state.and_assign(!RUNNING);
if self.state & CANCELLED != 0 { if &self.state & CANCELLED != 0 {
self.drop_data(); self.drop_data();
} else if self.state & RUN_AGAIN != 0 { } else if &self.state & RUN_AGAIN != 0 {
self.state &= !RUN_AGAIN; self.state.and_assign(!RUN_AGAIN);
self.schedule_run() self.schedule_run()
} }
} }
unsafe fn drop_data(&mut self) { unsafe fn drop_data(&self) {
if self.state & COMPLETED == 0 { if &self.state & COMPLETED == 0 {
ManuallyDrop::drop(&mut self.data.future); ManuallyDrop::drop(&mut self.data.get().deref_mut().future);
} else if self.state & EMPTIED == 0 { } else if &self.state & EMPTIED == 0 {
ManuallyDrop::drop(&mut self.data.result); ManuallyDrop::drop(&mut self.data.get().deref_mut().result);
} }
} }
} }

View file

@ -1,5 +1,5 @@
use std::cell::Cell; use std::cell::Cell;
use std::ops::{Add, Sub}; use std::ops::{Add, BitAnd, BitOr, Sub};
#[derive(Default)] #[derive(Default)]
pub struct NumCell<T> { pub struct NumCell<T> {
@ -7,14 +7,17 @@ pub struct NumCell<T> {
} }
impl<T> NumCell<T> { impl<T> NumCell<T> {
#[inline(always)]
pub fn new(t: T) -> Self { pub fn new(t: T) -> Self {
Self { t: Cell::new(t) } Self { t: Cell::new(t) }
} }
#[inline(always)]
pub fn replace(&self, n: T) -> T { pub fn replace(&self, n: T) -> T {
self.t.replace(n) self.t.replace(n)
} }
#[inline(always)]
pub fn load(&self) -> T pub fn load(&self) -> T
where where
T: Copy, T: Copy,
@ -22,6 +25,7 @@ impl<T> NumCell<T> {
self.t.get() self.t.get()
} }
#[inline(always)]
pub fn fetch_add(&self, n: T) -> T pub fn fetch_add(&self, n: T) -> T
where where
T: Copy + Add<T, Output = T>, T: Copy + Add<T, Output = T>,
@ -31,6 +35,7 @@ impl<T> NumCell<T> {
res res
} }
#[inline(always)]
pub fn fetch_sub(&self, n: T) -> T pub fn fetch_sub(&self, n: T) -> T
where where
T: Copy + Sub<T, Output = T>, T: Copy + Sub<T, Output = T>,
@ -39,4 +44,38 @@ impl<T> NumCell<T> {
self.t.set(res - n); self.t.set(res - n);
res res
} }
#[inline(always)]
pub fn or_assign(&self, n: T)
where
T: Copy + BitOr<Output = T>,
{
self.t.set(self.t.get() | n);
}
#[inline(always)]
pub fn and_assign(&self, n: T)
where
T: Copy + BitAnd<Output = T>,
{
self.t.set(self.t.get() & n);
}
}
impl<T: BitOr<Output = T> + Copy> BitOr<T> for &'_ NumCell<T> {
type Output = T;
#[inline(always)]
fn bitor(self, rhs: T) -> Self::Output {
self.t.get() | rhs
}
}
impl<T: BitAnd<Output = T> + Copy> BitAnd<T> for &'_ NumCell<T> {
type Output = T;
#[inline(always)]
fn bitand(self, rhs: T) -> Self::Output {
self.t.get() & rhs
}
} }

View file

@ -7,18 +7,21 @@ pub trait MutPtrExt<T: ?Sized> {
} }
impl<T: ?Sized> PtrExt<T> for *const T { impl<T: ?Sized> PtrExt<T> for *const T {
#[inline(always)]
unsafe fn deref<'a>(self) -> &'a T { unsafe fn deref<'a>(self) -> &'a T {
&*self &*self
} }
} }
impl<T: ?Sized> PtrExt<T> for *mut T { impl<T: ?Sized> PtrExt<T> for *mut T {
#[inline(always)]
unsafe fn deref<'a>(self) -> &'a T { unsafe fn deref<'a>(self) -> &'a T {
&*self &*self
} }
} }
impl<T: ?Sized> MutPtrExt<T> for *mut T { impl<T: ?Sized> MutPtrExt<T> for *mut T {
#[inline(always)]
unsafe fn deref_mut<'a>(self) -> &'a mut T { unsafe fn deref_mut<'a>(self) -> &'a mut T {
&mut *self &mut *self
} }