open_coroutine_hook/
lib.rs

1#![deny(
2    // The following are allowed by default lints according to
3    // https://doc.rust-lang.org/rustc/lints/listing/allowed-by-default.html
4    anonymous_parameters,
5    bare_trait_objects,
6    // elided_lifetimes_in_paths, // allow anonymous lifetime
7    missing_copy_implementations,
8    missing_debug_implementations,
9    missing_docs, // TODO: add documents
10    single_use_lifetimes, // TODO: fix lifetime names only used once
11    trivial_casts, // TODO: remove trivial casts in code
12    trivial_numeric_casts,
13    // unreachable_pub, allow clippy::redundant_pub_crate lint instead
14    // unsafe_code,
15    unstable_features,
16    unused_extern_crates,
17    unused_import_braces,
18    unused_qualifications,
19    unused_results,
20    variant_size_differences,
21
22    warnings, // treat all wanings as errors
23
24    clippy::all,
25    // clippy::restriction,
26    clippy::pedantic,
27    // clippy::nursery, // It's still under development
28    clippy::cargo,
29    unreachable_pub,
30)]
31#![allow(
32    // Some explicitly allowed Clippy lints, must have clear reason to allow
33    clippy::blanket_clippy_restriction_lints, // allow clippy::restriction
34    clippy::implicit_return, // actually omitting the return keyword is idiomatic Rust code
35    clippy::module_name_repetitions, // repeation of module name in a struct name is not big deal
36    clippy::multiple_crate_versions, // multi-version dependency crates is not able to fix
37    clippy::missing_errors_doc, // TODO: add error docs
38    clippy::missing_panics_doc, // TODO: add panic docs
39    clippy::panic_in_result_fn,
40    clippy::shadow_same, // Not too much bad
41    clippy::shadow_reuse, // Not too much bad
42    clippy::exhaustive_enums,
43    clippy::exhaustive_structs,
44    clippy::indexing_slicing,
45    clippy::separated_literal_suffix, // conflicts with clippy::unseparated_literal_suffix
46    clippy::single_char_lifetime_names, // TODO: change lifetime names
47)]
48//! see `https://github.com/acl-dev/open-coroutine`
49
50use once_cell::sync::OnceCell;
51use open_coroutine_core::co_pool::task::UserTaskFunc;
52use open_coroutine_core::config::Config;
53use open_coroutine_core::net::join::JoinHandle;
54use open_coroutine_core::net::{EventLoops, UserFunc};
55use open_coroutine_core::scheduler::SchedulableCoroutine;
56use std::ffi::{c_int, c_longlong, c_uint};
57use std::time::Duration;
58
59static HOOK: OnceCell<bool> = OnceCell::new();
60
61pub(crate) fn hook() -> bool {
62    HOOK.get().map_or_else(|| false, |v| *v)
63}
64
65#[allow(
66    dead_code,
67    missing_docs,
68    clippy::similar_names,
69    clippy::not_unsafe_ptr_arg_deref,
70    clippy::many_single_char_names,
71    clippy::unnecessary_cast
72)]
73pub mod syscall;
74
75/// Start the framework.
76#[no_mangle]
77pub extern "C" fn open_coroutine_init(config: Config) -> c_int {
78    EventLoops::init(&config);
79    _ = HOOK.get_or_init(|| config.hook());
80    0
81}
82
83/// Stop the framework.
84#[no_mangle]
85pub extern "C" fn open_coroutine_stop(secs: c_uint) -> c_int {
86    if EventLoops::stop(Duration::from_secs(u64::from(secs))).is_ok() {
87        return 0;
88    }
89    -1
90}
91
92///创建任务
93#[no_mangle]
94pub extern "C" fn task_crate(f: UserTaskFunc, param: usize, priority: c_longlong) -> JoinHandle {
95    EventLoops::submit_task(
96        None,
97        move |p| Some(f(p.unwrap_or(0))),
98        Some(param),
99        Some(priority),
100    )
101}
102
103///等待任务完成
104#[no_mangle]
105pub extern "C" fn task_join(handle: &JoinHandle) -> c_longlong {
106    match handle.join() {
107        Ok(ptr) => match ptr {
108            Ok(ptr) => match ptr {
109                Some(ptr) => c_longlong::try_from(ptr).expect("overflow"),
110                None => 0,
111            },
112            Err(_) => -1,
113        },
114        Err(_) => -1,
115    }
116}
117
118///等待任务完成
119#[no_mangle]
120pub extern "C" fn task_timeout_join(handle: &JoinHandle, ns_time: u64) -> c_longlong {
121    match handle.timeout_join(Duration::from_nanos(ns_time)) {
122        Ok(ptr) => match ptr {
123            Ok(ptr) => match ptr {
124                Some(ptr) => c_longlong::try_from(ptr).expect("overflow"),
125                None => 0,
126            },
127            Err(_) => -1,
128        },
129        Err(_) => -1,
130    }
131}
132
133///如果当前协程栈不够,切换到新栈上执行
134#[no_mangle]
135pub extern "C" fn maybe_grow_stack(
136    red_zone: usize,
137    stack_size: usize,
138    f: UserFunc,
139    param: usize,
140) -> c_longlong {
141    let red_zone = if red_zone > 0 {
142        red_zone
143    } else {
144        open_coroutine_core::common::default_red_zone()
145    };
146    let stack_size = if stack_size > 0 {
147        stack_size
148    } else {
149        open_coroutine_core::common::constants::DEFAULT_STACK_SIZE
150    };
151    if let Ok(r) = SchedulableCoroutine::maybe_grow_with(red_zone, stack_size, || f(param)) {
152        return c_longlong::try_from(r).expect("overflow");
153    }
154    -1
155}