The open-coroutine
is a simple, efficient and generic stackful-coroutine library.
English | 中文
- Preemptive(
not supported in windows
): even if the coroutine enters a dead loop, it can still be seized, see example; - Hook: you are free to use most of the slow syscall in coroutine, see supported syscall on unix/windows;
- 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;
- 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; - Priority: support custom task priority, note that coroutine priority is not open to users;
- Work Steal: internally using a lock free work steal queue;
- 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/...
; - Platforms: running on Linux, macOS and Windows;
- cancel coroutine/task;
- add metrics;
- add synchronization toolkit;
- support and compatibility for AF_XDP socket;
[dependencies]
# check https://crates.io/crates/open-coroutine
open-coroutine = "x.y.z"
#[open_coroutine::main]
fn main() {
//......
}
#[open_coroutine::main]
fn main() {
_ = open_coroutine::task!(|param| {
assert_eq!(param, "param");
}, "param");
}
#[open_coroutine::main]
fn main() {
_ = open_coroutine::task!(|param| {
assert_eq!(param, "param");
}, "param", 1/*the smaller the value, the higher the priority*/);
}
#[open_coroutine::main]
fn main() {
let task = open_coroutine::task!(|param| {
assert_eq!(param, "param");
}, "param", 1);
task.timeout_join(std::time::Duration::from_secs(1)).expect("timeout");
}
#[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]);
}, ());
}