Skip to content

Latest commit

 

History

History
88 lines (70 loc) · 3.67 KB

README.md

File metadata and controls

88 lines (70 loc) · 3.67 KB

open-coroutine

crates.io docs.rs LICENSE Build Status Codecov Average time to resolve an issue Percentage of issues still open

The open-coroutine is a simple, efficient and generic stackful-coroutine library.

English | 中文

🚀 Features

  • 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 system calls in coroutine;
  • 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 and coroutine priority;
  • Work Stealing: 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;

🕊 Roadmap

  • support #[open_coroutine::all_join] and #[open_coroutine::any_join] macro to wait coroutines;
  • add synchronization toolkit;
  • support and compatibility for AF_XDP socket;

📖 Quick Start

step1: add dependency to your Cargo.toml

[dependencies]
# check https://crates.io/crates/open-coroutine
open-coroutine = "x.y.z"

step2: add macro

#[open_coroutine::main]
fn main() {
    //......
}

step3: create a task

#[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: scalable stack(optional)

#[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]);
    }, ());
}

⚓ Learn

我有故事,你有酒吗?