Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,18 @@

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);
- [x] Hook: you are free to use most of the slow system calls in coroutine;
- [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

Expand Down Expand Up @@ -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]);
}, ());
Expand Down
88 changes: 88 additions & 0 deletions README_ZH.md
Original file line number Diff line number Diff line change
@@ -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)
4 changes: 2 additions & 2 deletions core/src/coroutine/korosensei.rs
Original file line number Diff line number Diff line change
Expand Up @@ -307,8 +307,6 @@ impl<'c, Param, Yield, Return> Coroutine<'c, Param, Yield, Return> {
stack_size: usize,
callback: F,
) -> std::io::Result<R> {
// 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 {
Expand All @@ -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<VecDeque<StackInfo>> = const { RefCell::new(VecDeque::new()) };
Expand Down
Loading