native_executor/
polyfill.rs1use futures_lite::future::block_on;
4use std::{panic::catch_unwind, sync::OnceLock};
5
6use crate::PlatformExecutor;
7
8#[derive(Debug, Clone, Copy, Default)]
11pub struct PolyfillExecutor;
12
13static EXECUTOR: OnceLock<async_executor::Executor<'static>> = OnceLock::new();
14
15fn global() -> &'static async_executor::Executor<'static> {
16 EXECUTOR.get_or_init(|| {
17 let exec = async_executor::Executor::new();
18 let num_threads = num_cpus::get().max(1);
19 for _ in 0..num_threads {
20 let executor = global();
21 std::thread::spawn(move || {
22 loop {
23 let _ = catch_unwind(|| {
24 block_on(executor.run(std::future::pending::<()>()));
25 });
26 }
27 });
28 }
29 exec
30 })
31}
32
33static MAIN_EXECUTOR: OnceLock<async_executor::Executor<'static>> = OnceLock::new();
34
35pub fn start_main_executor() {
42 let main_exec = async_executor::Executor::new();
43 MAIN_EXECUTOR
44 .set(main_exec)
45 .expect("Main executor already started");
46 let main_exec = MAIN_EXECUTOR
47 .get()
48 .expect("Unexpected error: main executor not set");
49 loop {
50 let _ = catch_unwind(|| {
51 block_on(main_exec.run(std::future::pending::<()>()));
52 });
53 }
54}
55
56fn main_executor() -> &'static async_executor::Executor<'static> {
57 MAIN_EXECUTOR.get().expect("Main executor not started")
58}
59
60impl PlatformExecutor for PolyfillExecutor {
61 fn exec(f: impl FnOnce() + Send + 'static, _priority: crate::Priority) {
62 global().spawn(async move { f() }).detach();
63 }
64 fn exec_after(
65 delay: std::time::Duration,
66 f: impl FnOnce() + Send + 'static,
67 _priority: crate::Priority,
68 ) {
69 global()
70 .spawn(async move {
71 async_io::Timer::after(delay).await;
72 f();
73 })
74 .detach();
75 }
76 fn exec_main(f: impl FnOnce() + Send + 'static) {
77 main_executor().spawn(async move { f() }).detach();
78 }
79}