autocommit 2022-01-08 23:04:44 CET
This commit is contained in:
parent
3336f1ab6a
commit
4efb187e24
3 changed files with 109 additions and 64 deletions
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue