Skip to content

Commit

Permalink
add stack pool (#349)
Browse files Browse the repository at this point in the history
  • Loading branch information
loongs-zhang authored Dec 23, 2024
2 parents d9a05c7 + d92351e commit 32b3bd3
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 6 deletions.
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

0 comments on commit 32b3bd3

Please sign in to comment.