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    clippy::test_attr_in_doctest,
48    unknown_lints, // for windows nightly
49    linker_messages, // for windows nightly
50)]
51#![doc = include_str!("../docs/en/hook.md")]
52
53use once_cell::sync::OnceCell;
54use open_coroutine_core::co_pool::task::UserTaskFunc;
55use open_coroutine_core::config::Config;
56use open_coroutine_core::net::join::JoinHandle;
57use open_coroutine_core::net::{EventLoops, UserFunc};
58use open_coroutine_core::scheduler::SchedulableCoroutine;
59use std::ffi::{c_int, c_longlong, c_uint};
60use std::time::Duration;
61
62static HOOK: OnceCell<bool> = OnceCell::new();
63
64pub(crate) fn hook() -> bool {
65    HOOK.get().map_or_else(|| false, |v| *v)
66}
67
68#[allow(
69    dead_code,
70    missing_docs,
71    clippy::similar_names,
72    clippy::not_unsafe_ptr_arg_deref,
73    clippy::many_single_char_names,
74    clippy::unnecessary_cast
75)]
76pub mod syscall;
77
78/// Start the framework.
79#[no_mangle]
80pub extern "C" fn open_coroutine_init(config: Config) -> c_int {
81    EventLoops::init(&config);
82    _ = HOOK.get_or_init(|| config.hook());
83    0
84}
85
86/// Stop the framework.
87#[no_mangle]
88pub extern "C" fn open_coroutine_stop(secs: c_uint) -> c_int {
89    if EventLoops::stop(Duration::from_secs(u64::from(secs))).is_ok() {
90        return 0;
91    }
92    -1
93}
94
95///创建任务
96#[no_mangle]
97pub extern "C" fn task_crate(f: UserTaskFunc, param: usize, priority: c_longlong) -> JoinHandle {
98    EventLoops::submit_task(
99        None,
100        move |p| Some(f(p.unwrap_or(0))),
101        Some(param),
102        Some(priority),
103    )
104}
105
106///尝试异步取消任务
107#[no_mangle]
108pub extern "C" fn task_cancel(handle: &JoinHandle) -> c_longlong {
109    match handle.get_name() {
110        Ok(name) => {
111            EventLoops::try_cancel_task(name);
112            0
113        }
114        Err(_) => -1,
115    }
116}
117
118///等待任务完成
119#[no_mangle]
120pub extern "C" fn task_join(handle: &JoinHandle) -> c_longlong {
121    match handle.join() {
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 task_timeout_join(handle: &JoinHandle, ns_time: u64) -> c_longlong {
136    match handle.timeout_join(Duration::from_nanos(ns_time)) {
137        Ok(ptr) => match ptr {
138            Ok(ptr) => match ptr {
139                Some(ptr) => c_longlong::try_from(ptr).expect("overflow"),
140                None => 0,
141            },
142            Err(_) => -1,
143        },
144        Err(_) => -1,
145    }
146}
147
148///如果当前协程栈不够,切换到新栈上执行
149#[no_mangle]
150pub extern "C" fn maybe_grow_stack(
151    red_zone: usize,
152    stack_size: usize,
153    f: UserFunc,
154    param: usize,
155) -> c_longlong {
156    let red_zone = if red_zone > 0 {
157        red_zone
158    } else {
159        open_coroutine_core::common::default_red_zone()
160    };
161    let stack_size = if stack_size > 0 {
162        stack_size
163    } else {
164        open_coroutine_core::common::constants::DEFAULT_STACK_SIZE
165    };
166    if let Ok(r) = SchedulableCoroutine::maybe_grow_with(red_zone, stack_size, || f(param)) {
167        return c_longlong::try_from(r).expect("overflow");
168    }
169    -1
170}