From d92351e92fa69eb4561300073d11bef995b588a6 Mon Sep 17 00:00:00 2001 From: dragon-zhang Date: Mon, 23 Dec 2024 14:39:42 +0800 Subject: [PATCH] add doc --- README.md | 10 ++-- README_ZH.md | 88 ++++++++++++++++++++++++++++++++ core/src/coroutine/korosensei.rs | 4 +- 3 files changed, 96 insertions(+), 6 deletions(-) create mode 100644 README_ZH.md diff --git a/README.md b/README.md index f47f4217..c27493c1 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,8 @@ The `open-coroutine` is a simple, efficient and generic stackful-coroutine library. +English | [中文](README_ZH.md) + ## 🚀 Features - [x] Preemptive(`not supported in windows`): even if the coroutine enters a dead loop, it can still be seized, see [example](https://github.com/loongs-zhang/open-coroutine/blob/master/open-coroutine/examples/preemptive.rs); @@ -17,9 +19,9 @@ The `open-coroutine` is a simple, efficient and generic stackful-coroutine libra - [x] Scalable: the size of the coroutine stack supports unlimited expansion without the cost of copying stack, and immediately shrinks to the original size after use, see [example](https://github.com/loongs-zhang/open-coroutine/blob/master/open-coroutine/examples/scalable_stack.rs); - [x] io_uring(`only in linux`): supports and is compatible with io_uring in terms of local file IO and network IO. If it's not supported on your system, it will fall back to non-blocking IO; - [x] Priority: support custom task and coroutine priority; -- [x] Work Stealing: internally using a lock free work steel queue; -- [x] Compatibility: the implementation of open-coroutine is no async, but it is compatible with async, which means you can use this crate in tokeno/sync-std/smol/...; -- [x] Platforms: running on Linux, MacOS and Windows; +- [x] Work Stealing: internally using a lock free work steal queue; +- [x] Compatibility: the implementation of open-coroutine is no async, but it is compatible with async, which means you can use this crate in tokio/async-std/smol/...; +- [x] Platforms: running on Linux, macOS and Windows; ## 🕊 Roadmap @@ -74,7 +76,7 @@ fn main() { }) .expect("allocate stack failed") } - println!("[coroutine] launched"); + println!("[task] launched"); // Use ~500KB of stack. recurse(50, &mut [0; 10240]); }, ()); diff --git a/README_ZH.md b/README_ZH.md new file mode 100644 index 00000000..fc49cbe1 --- /dev/null +++ b/README_ZH.md @@ -0,0 +1,88 @@ +# open-coroutine + +[![crates.io](https://img.shields.io/crates/v/open-coroutine.svg)](https://crates.io/crates/open-coroutine) +[![docs.rs](https://img.shields.io/badge/docs-release-blue)](https://docs.rs/open-coroutine) +[![LICENSE](https://img.shields.io/github/license/acl-dev/open-coroutine.svg?style=flat-square)](https://github.com/acl-dev/open-coroutine/blob/master/LICENSE-APACHE) +[![Build Status](https://github.com/acl-dev/open-coroutine/workflows/CI/badge.svg)](https://github.com/acl-dev/open-coroutine/actions) +[![Codecov](https://codecov.io/github/acl-dev/open-coroutine/graph/badge.svg?token=MSM3R7CBEX)](https://codecov.io/github/acl-dev/open-coroutine) +[![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/acl-dev/open-coroutine.svg)](http://isitmaintained.com/project/acl-dev/open-coroutine "Average time to resolve an issue") +[![Percentage of issues still open](http://isitmaintained.com/badge/open/acl-dev/open-coroutine.svg)](http://isitmaintained.com/project/acl-dev/open-coroutine "Percentage of issues still open") + +`open-coroutine`是一个简单、高效、通用的有栈协程库。 + +[English](README.md) | 中文 + +## 🚀 当前特性 + +- [x] 抢占调度(`不支持windows`): 即使协程进入死循环,它仍能被抢占,查看[例子](https://github.com/loongs-zhang/open-coroutine/blob/master/open-coroutine/examples/preemptive.rs); +- [x] Hook: 您可以在协程中自由使用大多数慢系统调用; +- [x] 可伸缩栈: 协程栈的大小支持无限制扩容而没有复制堆栈的开销,查看[例子](https://github.com/loongs-zhang/open-coroutine/blob/master/open-coroutine/examples/scalable_stack.rs); +- [x] io_uring(`只支持linux`): 在本地文件IO和网络IO方面支持并兼容io_uring。如果您的系统不支持,它将回退到NIO; +- [x] 优先级: 支持自定义任务和协程的优先级; +- [x] 任务窃取: 内部使用无锁任务窃取队列; +- [x] 兼容性: open-coroutine的实现是No async的,但它与async兼容,这意味着您可以在tokio/sync-std/smol/...中使用这个crate; +- [x] 跨平台: 支持Linux、macOS和Windows; + +## 🕊 未来计划 + +- [ ] 支持`#[open_coroutine::all_join]`和`#[open_coroutine::any_join]`宏; +- [ ] 增加并发工具包; +- [ ] 支持AF_XDP套接字; + +## 📖 快速接入 + +### step1: 在你的Cargo.toml中添加依赖 + +```toml +[dependencies] +# check https://crates.io/crates/open-coroutine +open-coroutine = "x.y.z" +``` + +### step2: 添加宏 + +```rust +#[open_coroutine::main] +fn main() { + //...... +} +``` + +### step3: 创建任务 + +```rust +#[open_coroutine::main] +fn main() { + let task = open_coroutine::task!(|param| { + assert_eq!(param, 1); + }, 1); + task.timeout_join(std::time::Duration::from_secs(1)).expect("timeout"); +} +``` + +### step4: 扩容栈(可选) + +```rust +#[open_coroutine::main] +fn main() { + _ = open_coroutine::task!(|_| { + fn recurse(i: u32, p: &mut [u8; 10240]) { + open_coroutine::maybe_grow!(|| { + // Ensure the stack allocation isn't optimized away. + unsafe { _ = std::ptr::read_volatile(&p) }; + if i > 0 { + recurse(i - 1, &mut [0; 10240]); + } + }) + .expect("allocate stack failed") + } + println!("[task] launched"); + // Use ~500KB of stack. + recurse(50, &mut [0; 10240]); + }, ()); +} +``` + +## ⚓ 学习更多 + +[我有故事,你有酒吗?](https://github.com/acl-dev/open-coroutine-docs) diff --git a/core/src/coroutine/korosensei.rs b/core/src/coroutine/korosensei.rs index 580e1a03..81004f3c 100644 --- a/core/src/coroutine/korosensei.rs +++ b/core/src/coroutine/korosensei.rs @@ -307,8 +307,6 @@ impl<'c, Param, Yield, Return> Coroutine<'c, Param, Yield, Return> { stack_size: usize, callback: F, ) -> std::io::Result { - // if we can't guess the remaining stack (unsupported on some platforms) we immediately grow - // the stack and then cache the new stack size (which we do know now because we allocated it. if let Some(co) = Self::current() { let remaining_stack = unsafe { co.remaining_stack() }; if remaining_stack >= red_zone { @@ -325,6 +323,8 @@ impl<'c, Param, Yield, Return> Coroutine<'c, Param, Yield, Return> { }); } // in thread + // if we can't guess the remaining stack (unsupported on some platforms) we immediately grow + // the stack and then cache the new stack size (which we do know now because we allocated it). thread_local! { #[allow(clippy::missing_const_for_thread_local)] static STACK_INFOS: RefCell> = const { RefCell::new(VecDeque::new()) };