Skip to main content

pistonite_cu/co/
runtime.rs

1use std::sync::LazyLock;
2
3use tokio::runtime::{Builder, Runtime};
4
5use crate::co::Handle;
6
7/// the current-thread runtime
8#[cfg(not(feature = "coroutine-heavy"))]
9static RUNTIME: LazyLock<Runtime> = LazyLock::new(|| {
10    Builder::new_current_thread()
11        .enable_all()
12        .build()
13        .expect("cannot create current-thread tokio runtime")
14});
15
16/// the multi-threaded, background runtime
17static BACKGROUND_RUNTIME: LazyLock<Runtime> = LazyLock::new(|| {
18    #[cfg(feature = "coroutine-heavy")]
19    {
20        Builder::new_multi_thread()
21            .enable_all()
22            .build()
23            .expect("cannot create heavy background tokio runtime")
24    }
25    #[cfg(not(feature = "coroutine-heavy"))]
26    {
27        Builder::new_multi_thread()
28            .worker_threads(1)
29            .enable_all()
30            .build()
31            .expect("cannot create background tokio runtime")
32    }
33});
34
35/// Get a reference of a runtime that contains the current thread
36pub(crate) fn foreground() -> &'static Runtime {
37    // only use the background runtime, because
38    // the foreground could be a background thread,
39    // and blocking it would block the background runtime
40    #[cfg(not(feature = "coroutine-heavy"))]
41    {
42        &RUNTIME
43    }
44    #[cfg(feature = "coroutine-heavy")]
45    {
46        &BACKGROUND_RUNTIME
47    }
48}
49
50pub(crate) fn background() -> &'static Runtime {
51    &BACKGROUND_RUNTIME
52}
53
54/// Run an async task using the current thread.
55///
56/// Consider using this as an entry point to some async procedure, if most of
57/// your program is sync.
58///
59/// To prevent misuse, this is only available without the `coroutine-heavy`
60/// feature.
61///
62/// Use [`spawn`] or [`run`] to run async tasks using the background thread(s)
63/// in both light and heavy async use cases.
64#[inline(always)]
65#[cfg(not(feature = "coroutine-heavy"))]
66pub fn block<F>(future: F) -> F::Output
67where
68    F: Future,
69{
70    RUNTIME.block_on(future)
71}
72
73/// Spawn a task onto the background runtime
74#[inline(always)]
75pub fn spawn<F>(future: F) -> Handle<F::Output>
76where
77    F: Future + Send + 'static,
78    F::Output: Send + 'static,
79{
80    Handle(BACKGROUND_RUNTIME.spawn(future))
81}
82
83/// Spawn a task onto the blocking pool of the background runtime
84///
85/// Since the light context only has one background thread,
86/// this is only enabled in heavy context to prevent misuse.
87#[inline(always)]
88#[cfg(feature = "coroutine-heavy")]
89pub fn spawn_blocking<F, R>(func: F) -> Handle<F::Output>
90where
91    F: FnOnce() -> R + Send + 'static,
92    R: Send + 'static,
93{
94    Handle(BACKGROUND_RUNTIME.spawn_blocking(func))
95}
96
97/// Run an async task using the background runtime
98#[inline(always)]
99pub fn run<F>(future: F) -> F::Output
100where
101    F: Future,
102{
103    BACKGROUND_RUNTIME.block_on(future)
104}