Skip to content

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

License

Apache-2.0, Unknown licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
Unknown
LICENSE-THIRD-PARTY
Notifications You must be signed in to change notification settings

acl-dev/open-coroutine

Folders and files

NameName
Last commit message
Last commit date

Latest commit

70f2837 Β· Mar 25, 2025
Mar 1, 2025
Mar 25, 2025
Feb 24, 2025
Mar 16, 2025
Dec 24, 2024
Mar 20, 2025
Oct 20, 2024
Mar 16, 2025
Mar 1, 2025
Jun 14, 2024
Jun 14, 2024
Mar 20, 2025
Mar 20, 2025
Nov 21, 2024
Oct 22, 2024
Jun 14, 2024

Repository files navigation

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 stackfull-coroutine library, you can use this as a performance replacement for IO thread pools, see why better.

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 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;

πŸ•Š Roadmap

  • add performance benchmark;
  • add metrics;
  • add synchronization toolkit;
  • support and compatibility for AF_XDP socket;

🏠 Architecture

Loading
graph TD
    subgraph ApplicationFramework
        Tower
        Actix-Web
        Rocket
        warp
        axum
    end
    subgraph MessageQueue
        RocketMQ
        Pulsar
    end
    subgraph RemoteProcedureCall
        Dubbo
        Tonic
        gRPC-rs
        Volo
    end
    subgraph Database
        MySQL
        Oracle
    end
    subgraph NetworkFramework
        Tokio
        monoio
        async-std
        smol
    end
    subgraph open-coroutine-architecture
        subgraph core
            Preemptive
            ScalableStack
            WorkSteal
            Priority
        end
        subgraph hook
            HookSyscall
        end
        subgraph macros
            open-coroutine::main
        end
        subgraph open-coroutine
        end
        hook -->|depends on| core
        open-coroutine -->|link| hook
        open-coroutine -->|depends on| macros
    end
    subgraph OperationSystem
        Linux
        macOS
        Windows
    end
    ApplicationFramework -->|maybe depends on| RemoteProcedureCall
    ApplicationFramework -->|maybe depends on| MessageQueue
    ApplicationFramework -->|maybe depends on| Database
    MessageQueue -->|depends on| NetworkFramework
    RemoteProcedureCall -->|depends on| NetworkFramework
    NetworkFramework -->|runs on| OperationSystem
    NetworkFramework -->|can depends on| open-coroutine-architecture
    Database -->|runs on| OperationSystem
    open-coroutine-architecture -->|runs on| OperationSystem

πŸ“– Quick Start

step1: add dependency to your Cargo.toml

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

step2: add open_coroutine::main macro

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

step3: create a task

#[open_coroutine::main]
fn main() {
    _ = open_coroutine::task!(|param| {
        assert_eq!(param, "param");
    }, "param");
}

πŸͺΆ Advanced Usage

create a task with priority

#[open_coroutine::main]
fn main() {
    _ = open_coroutine::task!(|param| {
        assert_eq!(param, "param");
    }, "param", 1/*the smaller the value, the higher the priority*/);
}

wait until the task is completed or timed out

#[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");
}

wait until any task is completed or timed out

#[open_coroutine::main]
fn main() {
    let result = open_coroutine::any_timeout_join!(
        std::time::Duration::from_secs(1),
        open_coroutine::task!(|_| 1, ()),
        open_coroutine::task!(|_| 2, ()),
        open_coroutine::task!(|_| 3, ())
    ).expect("timeout");
}

scalable stack

#[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 More

Old Docs Here

πŸ‘ Credits

This crate was inspired by the following projects:

Thanks to those who have provided assistance:

Amanieu bjorn3 workingjubilee Noratrieb

About

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

Topics

Resources

License

Apache-2.0, Unknown licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
Unknown
LICENSE-THIRD-PARTY

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages