async_engine: move scheduler into workspace crate
This commit is contained in:
parent
b7ecf700fa
commit
03d3876888
7 changed files with 205 additions and 182 deletions
10
Cargo.lock
generated
10
Cargo.lock
generated
|
|
@ -639,6 +639,15 @@ dependencies = [
|
||||||
"libloading",
|
"libloading",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jay-async-engine"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"jay-time",
|
||||||
|
"jay-tracy",
|
||||||
|
"jay-utils",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jay-cmm"
|
name = "jay-cmm"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|
@ -672,6 +681,7 @@ dependencies = [
|
||||||
"isnt 0.2.0",
|
"isnt 0.2.0",
|
||||||
"jay-algorithms",
|
"jay-algorithms",
|
||||||
"jay-ash",
|
"jay-ash",
|
||||||
|
"jay-async-engine",
|
||||||
"jay-cmm",
|
"jay-cmm",
|
||||||
"jay-config",
|
"jay-config",
|
||||||
"jay-criteria",
|
"jay-criteria",
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ members = [
|
||||||
"cmm",
|
"cmm",
|
||||||
"time",
|
"time",
|
||||||
"tracy",
|
"tracy",
|
||||||
|
"async-engine",
|
||||||
"toml-config",
|
"toml-config",
|
||||||
"algorithms",
|
"algorithms",
|
||||||
"toml-spec",
|
"toml-spec",
|
||||||
|
|
@ -55,6 +56,7 @@ jay-criteria = { version = "0.1.0", path = "criteria" }
|
||||||
jay-cmm = { version = "0.1.0", path = "cmm" }
|
jay-cmm = { version = "0.1.0", path = "cmm" }
|
||||||
jay-time = { version = "0.1.0", path = "time" }
|
jay-time = { version = "0.1.0", path = "time" }
|
||||||
jay-tracy = { version = "0.1.0", path = "tracy" }
|
jay-tracy = { version = "0.1.0", path = "tracy" }
|
||||||
|
jay-async-engine = { version = "0.1.0", path = "async-engine" }
|
||||||
|
|
||||||
uapi = "0.2.13"
|
uapi = "0.2.13"
|
||||||
thiserror = "2.0.11"
|
thiserror = "2.0.11"
|
||||||
|
|
@ -117,5 +119,5 @@ opt-level = 3
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
rc_tracking = []
|
rc_tracking = []
|
||||||
it = []
|
it = ["jay-async-engine/it"]
|
||||||
tracy = ["jay-tracy/tracy"]
|
tracy = ["jay-tracy/tracy", "jay-async-engine/tracy"]
|
||||||
|
|
|
||||||
14
async-engine/Cargo.toml
Normal file
14
async-engine/Cargo.toml
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
[package]
|
||||||
|
name = "jay-async-engine"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
license = "GPL-3.0-only"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
jay-time = { version = "0.1.0", path = "../time" }
|
||||||
|
jay-tracy = { version = "0.1.0", path = "../tracy" }
|
||||||
|
jay-utils = { version = "0.1.0", path = "../utils" }
|
||||||
|
|
||||||
|
[features]
|
||||||
|
it = []
|
||||||
|
tracy = ["jay-tracy/tracy"]
|
||||||
|
|
@ -1,11 +1,9 @@
|
||||||
use {
|
use {
|
||||||
crate::{
|
crate::{AsyncEngine, Phase},
|
||||||
async_engine::{AsyncEngine, Phase},
|
jay_tracy::ZoneName,
|
||||||
tracy::ZoneName,
|
jay_utils::{
|
||||||
utils::{
|
numcell::NumCell,
|
||||||
numcell::NumCell,
|
ptr_ext::{MutPtrExt, PtrExt},
|
||||||
ptr_ext::{MutPtrExt, PtrExt},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
std::{
|
std::{
|
||||||
cell::{Cell, UnsafeCell},
|
cell::{Cell, UnsafeCell},
|
||||||
|
|
@ -142,7 +140,7 @@ impl AsyncEngine {
|
||||||
}),
|
}),
|
||||||
waker: Cell::new(None),
|
waker: Cell::new(None),
|
||||||
queue: self.clone(),
|
queue: self.clone(),
|
||||||
zone: create_zone_name!("task:{}", name),
|
zone: jay_tracy::create_zone_name!("task:{}", name),
|
||||||
});
|
});
|
||||||
unsafe {
|
unsafe {
|
||||||
f.schedule_run();
|
f.schedule_run();
|
||||||
|
|
@ -254,7 +252,7 @@ impl<T, F: Future<Output = T>> Task<T, F> {
|
||||||
|
|
||||||
let mut ctx = Context::from_waker(&waker);
|
let mut ctx = Context::from_waker(&waker);
|
||||||
let poll = {
|
let poll = {
|
||||||
dynamic_zone!(self.zone);
|
jay_tracy::dynamic_zone!(self.zone);
|
||||||
Pin::new_unchecked(&mut *data.future).poll(&mut ctx)
|
Pin::new_unchecked(&mut *data.future).poll(&mut ctx)
|
||||||
};
|
};
|
||||||
if let Poll::Ready(d) = poll {
|
if let Poll::Ready(d) = poll {
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use {
|
use {
|
||||||
crate::async_engine::AsyncEngine,
|
crate::AsyncEngine,
|
||||||
std::{
|
std::{
|
||||||
future::Future,
|
future::Future,
|
||||||
pin::Pin,
|
pin::Pin,
|
||||||
168
async-engine/src/lib.rs
Normal file
168
async-engine/src/lib.rs
Normal file
|
|
@ -0,0 +1,168 @@
|
||||||
|
mod ae_task;
|
||||||
|
mod ae_yield;
|
||||||
|
|
||||||
|
pub use {ae_task::SpawnedFuture, ae_yield::Yield};
|
||||||
|
use {
|
||||||
|
crate::ae_task::Runnable,
|
||||||
|
jay_time::Time,
|
||||||
|
jay_utils::{array, numcell::NumCell, syncqueue::SyncQueue},
|
||||||
|
std::{
|
||||||
|
cell::{Cell, RefCell},
|
||||||
|
collections::VecDeque,
|
||||||
|
future::Future,
|
||||||
|
rc::Rc,
|
||||||
|
task::Waker,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Eq, PartialEq)]
|
||||||
|
pub enum Phase {
|
||||||
|
EventHandling,
|
||||||
|
Layout,
|
||||||
|
PostLayout,
|
||||||
|
Present,
|
||||||
|
}
|
||||||
|
const NUM_PHASES: usize = 4;
|
||||||
|
|
||||||
|
pub struct AsyncEngine {
|
||||||
|
num_queued: NumCell<usize>,
|
||||||
|
queues: [SyncQueue<Runnable>; NUM_PHASES],
|
||||||
|
iteration: NumCell<u64>,
|
||||||
|
yields: SyncQueue<Waker>,
|
||||||
|
stash: RefCell<VecDeque<Runnable>>,
|
||||||
|
yield_stash: RefCell<VecDeque<Waker>>,
|
||||||
|
stopped: Cell<bool>,
|
||||||
|
now: Cell<Option<Time>>,
|
||||||
|
#[cfg(feature = "it")]
|
||||||
|
idle: Cell<Option<Waker>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsyncEngine {
|
||||||
|
pub fn new() -> Rc<Self> {
|
||||||
|
Rc::new(Self {
|
||||||
|
num_queued: Default::default(),
|
||||||
|
queues: array::from_fn(|_| Default::default()),
|
||||||
|
iteration: Default::default(),
|
||||||
|
yields: Default::default(),
|
||||||
|
stash: Default::default(),
|
||||||
|
yield_stash: Default::default(),
|
||||||
|
stopped: Cell::new(false),
|
||||||
|
now: Default::default(),
|
||||||
|
#[cfg(feature = "it")]
|
||||||
|
idle: Default::default(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn stop(&self) {
|
||||||
|
self.stopped.set(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clear(&self) {
|
||||||
|
self.stash.borrow_mut().clear();
|
||||||
|
self.yield_stash.borrow_mut().clear();
|
||||||
|
self.yields.take();
|
||||||
|
for queue in &self.queues {
|
||||||
|
queue.take();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn spawn<T, F: Future<Output = T> + 'static>(
|
||||||
|
self: &Rc<Self>,
|
||||||
|
name: &str,
|
||||||
|
f: F,
|
||||||
|
) -> SpawnedFuture<T> {
|
||||||
|
self.spawn_(name, Phase::EventHandling, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn spawn2<T, F: Future<Output = T> + 'static>(
|
||||||
|
self: &Rc<Self>,
|
||||||
|
name: &str,
|
||||||
|
phase: Phase,
|
||||||
|
f: F,
|
||||||
|
) -> SpawnedFuture<T> {
|
||||||
|
self.spawn_(name, phase, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn yield_now(self: &Rc<Self>) -> Yield {
|
||||||
|
Yield {
|
||||||
|
iteration: self.iteration(),
|
||||||
|
queue: self.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn dispatch(&self) {
|
||||||
|
let mut stash = self.stash.borrow_mut();
|
||||||
|
let mut yield_stash = self.yield_stash.borrow_mut();
|
||||||
|
loop {
|
||||||
|
if self.num_queued.get() == 0 {
|
||||||
|
#[cfg(feature = "it")]
|
||||||
|
if let Some(idle) = self.idle.take() {
|
||||||
|
idle.wake();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
self.now.take();
|
||||||
|
let mut phase = 0;
|
||||||
|
while phase < NUM_PHASES {
|
||||||
|
self.queues[phase].swap(&mut *stash);
|
||||||
|
if stash.is_empty() {
|
||||||
|
phase += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
self.num_queued.fetch_sub(stash.len());
|
||||||
|
while let Some(runnable) = stash.pop_front() {
|
||||||
|
runnable.run();
|
||||||
|
if self.stopped.get() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.iteration.fetch_add(1);
|
||||||
|
self.yields.swap(&mut *yield_stash);
|
||||||
|
while let Some(waker) = yield_stash.pop_front() {
|
||||||
|
waker.wake();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "it")]
|
||||||
|
pub async fn idle(&self) {
|
||||||
|
use std::{future::poll_fn, task::Poll};
|
||||||
|
let mut register = true;
|
||||||
|
poll_fn(|ctx| {
|
||||||
|
if register {
|
||||||
|
self.idle.set(Some(ctx.waker().clone()));
|
||||||
|
register = false;
|
||||||
|
Poll::Pending
|
||||||
|
} else {
|
||||||
|
Poll::Ready(())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
|
fn push(&self, runnable: Runnable, phase: Phase) {
|
||||||
|
self.queues[phase as usize].push(runnable);
|
||||||
|
self.num_queued.fetch_add(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn push_yield(&self, waker: Waker) {
|
||||||
|
self.yields.push(waker);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn iteration(&self) -> u64 {
|
||||||
|
self.iteration.get()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn now(&self) -> Time {
|
||||||
|
match self.now.get() {
|
||||||
|
Some(t) => t,
|
||||||
|
None => {
|
||||||
|
let now = Time::now_unchecked();
|
||||||
|
self.now.set(Some(now));
|
||||||
|
now
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,170 +1 @@
|
||||||
mod ae_task;
|
pub use jay_async_engine::*;
|
||||||
mod ae_yield;
|
|
||||||
|
|
||||||
pub use {crate::async_engine::ae_yield::Yield, ae_task::SpawnedFuture};
|
|
||||||
use {
|
|
||||||
crate::{
|
|
||||||
async_engine::ae_task::Runnable,
|
|
||||||
time::Time,
|
|
||||||
utils::{array, numcell::NumCell, syncqueue::SyncQueue},
|
|
||||||
},
|
|
||||||
std::{
|
|
||||||
cell::{Cell, RefCell},
|
|
||||||
collections::VecDeque,
|
|
||||||
future::Future,
|
|
||||||
rc::Rc,
|
|
||||||
task::Waker,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Eq, PartialEq)]
|
|
||||||
pub enum Phase {
|
|
||||||
EventHandling,
|
|
||||||
Layout,
|
|
||||||
PostLayout,
|
|
||||||
Present,
|
|
||||||
}
|
|
||||||
const NUM_PHASES: usize = 4;
|
|
||||||
|
|
||||||
pub struct AsyncEngine {
|
|
||||||
num_queued: NumCell<usize>,
|
|
||||||
queues: [SyncQueue<Runnable>; NUM_PHASES],
|
|
||||||
iteration: NumCell<u64>,
|
|
||||||
yields: SyncQueue<Waker>,
|
|
||||||
stash: RefCell<VecDeque<Runnable>>,
|
|
||||||
yield_stash: RefCell<VecDeque<Waker>>,
|
|
||||||
stopped: Cell<bool>,
|
|
||||||
now: Cell<Option<Time>>,
|
|
||||||
#[cfg(feature = "it")]
|
|
||||||
idle: Cell<Option<Waker>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AsyncEngine {
|
|
||||||
pub fn new() -> Rc<Self> {
|
|
||||||
Rc::new(Self {
|
|
||||||
num_queued: Default::default(),
|
|
||||||
queues: array::from_fn(|_| Default::default()),
|
|
||||||
iteration: Default::default(),
|
|
||||||
yields: Default::default(),
|
|
||||||
stash: Default::default(),
|
|
||||||
yield_stash: Default::default(),
|
|
||||||
stopped: Cell::new(false),
|
|
||||||
now: Default::default(),
|
|
||||||
#[cfg(feature = "it")]
|
|
||||||
idle: Default::default(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn stop(&self) {
|
|
||||||
self.stopped.set(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn clear(&self) {
|
|
||||||
self.stash.borrow_mut().clear();
|
|
||||||
self.yield_stash.borrow_mut().clear();
|
|
||||||
self.yields.take();
|
|
||||||
for queue in &self.queues {
|
|
||||||
queue.take();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn spawn<T, F: Future<Output = T> + 'static>(
|
|
||||||
self: &Rc<Self>,
|
|
||||||
name: &str,
|
|
||||||
f: F,
|
|
||||||
) -> SpawnedFuture<T> {
|
|
||||||
self.spawn_(name, Phase::EventHandling, f)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn spawn2<T, F: Future<Output = T> + 'static>(
|
|
||||||
self: &Rc<Self>,
|
|
||||||
name: &str,
|
|
||||||
phase: Phase,
|
|
||||||
f: F,
|
|
||||||
) -> SpawnedFuture<T> {
|
|
||||||
self.spawn_(name, phase, f)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn yield_now(self: &Rc<Self>) -> Yield {
|
|
||||||
Yield {
|
|
||||||
iteration: self.iteration(),
|
|
||||||
queue: self.clone(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn dispatch(&self) {
|
|
||||||
let mut stash = self.stash.borrow_mut();
|
|
||||||
let mut yield_stash = self.yield_stash.borrow_mut();
|
|
||||||
loop {
|
|
||||||
if self.num_queued.get() == 0 {
|
|
||||||
#[cfg(feature = "it")]
|
|
||||||
if let Some(idle) = self.idle.take() {
|
|
||||||
idle.wake();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
self.now.take();
|
|
||||||
let mut phase = 0;
|
|
||||||
while phase < NUM_PHASES {
|
|
||||||
self.queues[phase].swap(&mut *stash);
|
|
||||||
if stash.is_empty() {
|
|
||||||
phase += 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
self.num_queued.fetch_sub(stash.len());
|
|
||||||
while let Some(runnable) = stash.pop_front() {
|
|
||||||
runnable.run();
|
|
||||||
if self.stopped.get() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.iteration.fetch_add(1);
|
|
||||||
self.yields.swap(&mut *yield_stash);
|
|
||||||
while let Some(waker) = yield_stash.pop_front() {
|
|
||||||
waker.wake();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "it")]
|
|
||||||
pub async fn idle(&self) {
|
|
||||||
use std::{future::poll_fn, task::Poll};
|
|
||||||
let mut register = true;
|
|
||||||
poll_fn(|ctx| {
|
|
||||||
if register {
|
|
||||||
self.idle.set(Some(ctx.waker().clone()));
|
|
||||||
register = false;
|
|
||||||
Poll::Pending
|
|
||||||
} else {
|
|
||||||
Poll::Ready(())
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
fn push(&self, runnable: Runnable, phase: Phase) {
|
|
||||||
self.queues[phase as usize].push(runnable);
|
|
||||||
self.num_queued.fetch_add(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn push_yield(&self, waker: Waker) {
|
|
||||||
self.yields.push(waker);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn iteration(&self) -> u64 {
|
|
||||||
self.iteration.get()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn now(&self) -> Time {
|
|
||||||
match self.now.get() {
|
|
||||||
Some(t) => t,
|
|
||||||
None => {
|
|
||||||
let now = Time::now_unchecked();
|
|
||||||
self.now.set(Some(now));
|
|
||||||
now
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue