diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..4fffb2f89cbd8f2169ce9914bd16bd43785bb368 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/target +/Cargo.lock diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..32616afc2043187c358a33b00ff80c9800f442a1 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,29 @@ +[package] +edition = "2021" +name = "async-executor" +version = "0.1.0" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[features] +default = ["alloc"] + +alloc = ["stdlib/alloc", "async-task/alloc"] +std = ["stdlib/std", "async-task/std"] + +multiple_thread = [] +signle_thread = [] + + +[dependencies] +stdlib = { path = "../stdlib", default-features = false } +async-task = { path = "../async-task", default-features = false } +utils = { path = "../utils" } +slab = { version = "0.4.6", default-features = false } + +[dev-dependencies] +async-io = "1.6.0" + +[profile.dev] +panic = "abort" +[profile.release] +panic = "abort" \ No newline at end of file diff --git a/README.en.md b/README.en.md index a800c539093664d16ba5e46dfc24b2da9d57834c..4d83a8fae8fe92d1fd9597a31965f98949089b5c 100644 --- a/README.en.md +++ b/README.en.md @@ -1,36 +1,6 @@ # async-executor #### Description -异步执行器 +An asynchronous executor for asynchronous tasks, which is used to schedule and execute asynchronous tasks `Task`. -#### Software Architecture -Software architecture description -#### Installation - -1. xxxx -2. xxxx -3. xxxx - -#### Instructions - -1. xxxx -2. xxxx -3. xxxx - -#### Contribution - -1. Fork the repository -2. Create Feat_xxx branch -3. Commit your code -4. Create Pull Request - - -#### Gitee Feature - -1. You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md -2. Gitee blog [blog.gitee.com](https://blog.gitee.com) -3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore) -4. The most valuable open source project [GVP](https://gitee.com/gvp) -5. The manual of Gitee [https://gitee.com/help](https://gitee.com/help) -6. The most popular members [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/) diff --git a/README.md b/README.md index c6760619815d71a811a1ddc3d942a227b60d9c66..aefff22af316d9aeb26856b4d1090520be661ef4 100644 --- a/README.md +++ b/README.md @@ -1,37 +1,5 @@ # async-executor #### 介绍 -异步执行器 +异步任务的异步执行器,用来对异步任务 `Task` 进行调度执行。 -#### 软件架构 -软件架构说明 - - -#### 安装教程 - -1. xxxx -2. xxxx -3. xxxx - -#### 使用说明 - -1. xxxx -2. xxxx -3. xxxx - -#### 参与贡献 - -1. Fork 本仓库 -2. 新建 Feat_xxx 分支 -3. 提交代码 -4. 新建 Pull Request - - -#### 特技 - -1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md -2. Gitee 官方博客 [blog.gitee.com](https://blog.gitee.com) -3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解 Gitee 上的优秀开源项目 -4. [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目 -5. Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help) -6. Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/) diff --git a/examples/demo.rs b/examples/demo.rs new file mode 100644 index 0000000000000000000000000000000000000000..f4d70bc6ee37537cad286867239621656d70336e --- /dev/null +++ b/examples/demo.rs @@ -0,0 +1,21 @@ +use async_executor::LocalExecutor; +fn main() { + struct PP; + impl core::future::Future for PP { + type Output = u8; + fn poll( + self: std::pin::Pin<&mut Self>, + _cx: &mut std::task::Context<'_>, + ) -> core::task::Poll { + core::task::Poll::Pending + } + } + let local_executor: LocalExecutor = LocalExecutor::new(); + local_executor + .spawn(async { + let t = PP; + t.await; + }) + .detach(); + local_executor.run(); +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..7aab6b87c04862911796a57727e6ead3b1f27f02 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,108 @@ +#![cfg_attr(feature = "alloc", no_std)] + +extern crate alloc; + +use alloc::rc::Rc; +use async_task::{Runnable, Task}; +use core::cell::RefCell; +use core::future::Future; +use core::panic::{RefUnwindSafe, UnwindSafe}; +use core::task::Waker; +use slab::Slab; +use stdlib::collections::Unbounded; +use utils::Defer; +pub struct LocalExecutor { + container: Rc, +} + +unsafe impl Sync for LocalExecutor {} +impl UnwindSafe for LocalExecutor {} +impl RefUnwindSafe for LocalExecutor {} + +impl LocalExecutor { + /// Creates a new executor + /// + /// # Examples + /// + /// ``` + /// use async_executor::LocalExecutor; + /// let exe = LocalExecutor::new(); + /// + /// ``` + pub fn new() -> LocalExecutor { + LocalExecutor { + container: Rc::new(Container::new()), + } + } + /// Spawns a task onto the global executor + pub fn spawn(&self, future: impl Future) -> Task { + // let mut self_container = self.container.borrow_mut(); + // 获得活动列表,列表中放的是 Runnable + + let mut actives = self.container.actives.borrow_mut(); + // 当 future 完成,从 actives 中删除 + let index = actives.vacant_key(); + let container = self.container.clone(); + let future = async move { + let _defer = Defer((), |_| { + let mut active = container.actives.borrow_mut(); + active.try_remove(index).map(|wk| drop(wk)); + }); + future.await + }; + + let (runnable, task) = unsafe { async_task::spawn_unchecked(future, self.schedule()) }; + actives.insert(runnable.waker()); + runnable.schedule(); + task + } + + /// 运行 executor,直到给定的 future 完成 + pub fn run(&self) { + while let Ok(running) = self.container.queue.pop() { + running.run(); + } + } + + /// Returns a function that schedules a runnable task when it gets woken up. + fn schedule(&self) -> impl Fn(Runnable) + 'static { + let container = self.container.clone(); + move |runnable| { + unsafe { container.queue.push(runnable).unwrap_unchecked() }; + } + } +} + +impl Default for LocalExecutor { + fn default() -> Self { + LocalExecutor::new() + } +} + +impl Drop for LocalExecutor { + fn drop(&mut self) { + let mut active = self.container.actives.borrow_mut(); + for w in active.drain() { + w.wake(); + } + drop(active); + while self.container.queue.pop().is_ok() {} + } +} + +struct Container { + /// The global queue. + queue: Unbounded, + /// 当前活动的列表 + actives: RefCell>, +} + +impl Container { + /// Create container for a new executor + fn new() -> Container { + Container { + queue: Unbounded::new(), + actives: RefCell::new(Slab::new()), + } + } +}