1#[cfg(not(target_arch = "wasm32"))]
2pub use std::thread::*;
3#[cfg(target_arch = "wasm32")]
4pub use wasm_thread::*;
5
6#[cfg(target_family = "wasm")]
7mod main_thread {
8 use crate::channels::{mpsc, oneshot};
9 use std::{future::Future, pin::Pin};
10
11 pub type TaskForMainThread = Pin<Box<dyn 'static + Send + Future<Output = ()>>>;
12
13 static MAIN_THREAD_TASK_SENDER: once_cell::sync::OnceCell<
14 mpsc::UnboundedSender<TaskForMainThread>,
15 > = once_cell::sync::OnceCell::new();
16
17 pub fn main_thread_init() {
18 assert!(
19 !super::is_web_worker_thread(),
20 "Must be called in the main thread!"
21 );
22
23 MAIN_THREAD_TASK_SENDER.get_or_init(|| {
24 let (task_sender, mut task_receiver) = mpsc::unbounded_channel();
25 wasm_bindgen_futures::spawn_local(async move {
26 while let Some(task) = task_receiver.recv().await {
27 wasm_bindgen_futures::spawn_local(task);
28 }
29 });
30 task_sender
31 });
32 }
33
34 pub fn start_task_in_main_thread<F>(task: F)
35 where
36 F: 'static + Send + Future<Output = ()>,
37 {
38 let sender = MAIN_THREAD_TASK_SENDER
39 .get()
40 .expect("main thread not initialized");
41 let _ = sender.send(Box::pin(task));
42 }
43
44 pub async fn run_task_in_main_thread<F, T>(task: F) -> Option<T>
45 where
46 T: 'static + Send,
47 F: 'static + Send + Future<Output = T>,
48 {
49 let sender = MAIN_THREAD_TASK_SENDER
50 .get()
51 .expect("main thread not initialized");
52 let (tx, rx) = oneshot::channel();
53 let _ = sender.send(Box::pin(async move {
54 let _ = tx.send(task.await);
55 }));
56 rx.await.ok()
57 }
58
59 pub async fn run_async_fn_in_main_thread<F, FU, T>(f: F) -> Option<T>
60 where
61 T: 'static + Send,
62 FU: Future<Output = T>,
63 F: 'static + Send + FnOnce() -> FU,
64 {
65 let sender = MAIN_THREAD_TASK_SENDER
66 .get()
67 .expect("main thread not initialized");
68 let (tx, rx) = oneshot::channel();
69 let _ = sender.send(Box::pin(async move {
70 wasm_bindgen_futures::spawn_local(async move {
71 let _ = tx.send(f().await);
72 })
73 }));
74 rx.await.ok()
75 }
76
77 pub fn run_async_fn_in_main_thread_blocking<F, FU, T>(f: F) -> Option<T>
78 where
79 T: 'static + Send,
80 FU: Future<Output = T>,
81 F: 'static + Send + FnOnce() -> FU,
82 {
83 let sender = MAIN_THREAD_TASK_SENDER
84 .get()
85 .expect("main thread not initialized");
86 let (tx, rx) = oneshot::channel();
87 let _ = sender.send(Box::pin(async move {
88 wasm_bindgen_futures::spawn_local(async move {
89 let _ = tx.send(f().await);
90 })
91 }));
92 rx.blocking_recv().ok()
93 }
94}
95#[cfg(target_family = "wasm")]
96pub use main_thread::*;