1#[cfg(not(target_arch = "wasm32"))]
22use crate::futures::executor::ThreadPool;
23use parking_lot::Mutex;
24use std::{
25 any::Any,
26 future::Future,
27 sync::mpsc::{self, Receiver, Sender},
28};
29use uuid::Uuid;
30
31#[cfg(not(target_arch = "wasm32"))]
34pub trait AsyncTaskResult: Any + Send + 'static {
35 fn into_any(self: Box<Self>) -> Box<dyn Any>;
36}
37
38#[cfg(not(target_arch = "wasm32"))]
39impl<T> AsyncTaskResult for T
40where
41 T: Any + Send + 'static,
42{
43 fn into_any(self: Box<Self>) -> Box<dyn Any> {
44 self
45 }
46}
47
48#[cfg(not(target_arch = "wasm32"))]
49pub trait AsyncTask<R: AsyncTaskResult>: Future<Output = R> + Send + 'static {}
50
51#[cfg(not(target_arch = "wasm32"))]
52impl<T, R: AsyncTaskResult> AsyncTask<R> for T where T: Future<Output = R> + Send + 'static {}
53
54#[cfg(target_arch = "wasm32")]
57pub trait AsyncTaskResult: Any + 'static {
58 fn into_any(self: Box<Self>) -> Box<dyn Any>;
59}
60
61#[cfg(target_arch = "wasm32")]
62impl<T> AsyncTaskResult for T
63where
64 T: Any + 'static,
65{
66 fn into_any(self: Box<Self>) -> Box<dyn Any> {
67 self
68 }
69}
70
71#[cfg(target_arch = "wasm32")]
72pub trait AsyncTask<R: AsyncTaskResult>: Future<Output = R> + 'static {}
73
74#[cfg(target_arch = "wasm32")]
75impl<T, R: AsyncTaskResult> AsyncTask<R> for T where T: Future<Output = R> + 'static {}
76
77impl dyn AsyncTaskResult {
80 pub fn downcast<T: AsyncTaskResult>(self: Box<Self>) -> Result<Box<T>, Box<dyn Any>> {
81 self.into_any().downcast()
82 }
83}
84
85pub struct TaskResult {
86 pub id: Uuid,
87 pub payload: Box<dyn AsyncTaskResult>,
88}
89
90pub struct TaskPool {
91 #[cfg(not(target_arch = "wasm32"))]
92 thread_pool: ThreadPool,
93 sender: Sender<TaskResult>,
94 receiver: Mutex<Receiver<TaskResult>>,
95}
96
97impl Default for TaskPool {
98 fn default() -> Self {
99 Self::new()
100 }
101}
102
103impl TaskPool {
104 #[inline]
105 pub fn new() -> Self {
106 let (sender, receiver) = mpsc::channel();
107 Self {
108 #[cfg(not(target_arch = "wasm32"))]
109 thread_pool: ThreadPool::new().unwrap(),
110 sender,
111 receiver: Mutex::new(receiver),
112 }
113 }
114
115 #[inline]
116 #[cfg(target_arch = "wasm32")]
117 pub fn spawn_task<F>(&self, future: F)
118 where
119 F: Future<Output = ()> + 'static,
120 {
121 crate::wasm_bindgen_futures::spawn_local(future);
122 }
123
124 #[inline]
125 #[cfg(not(target_arch = "wasm32"))]
126 pub fn spawn_task<F>(&self, future: F)
127 where
128 F: Future<Output = ()> + Send + 'static,
129 {
130 self.thread_pool.spawn_ok(future);
131 }
132
133 #[inline]
134 pub fn spawn_with_result<F, T>(&self, future: F) -> Uuid
135 where
136 F: AsyncTask<T>,
137 T: AsyncTaskResult,
138 {
139 let id = Uuid::new_v4();
140 let sender = self.sender.clone();
141 self.spawn_task(async move {
142 let result = future.await;
143 sender
144 .send(TaskResult {
145 id,
146 payload: Box::new(result),
147 })
148 .unwrap();
149 });
150 id
151 }
152
153 #[inline]
154 pub fn next_task_result(&self) -> Option<TaskResult> {
155 self.receiver.lock().try_recv().ok()
156 }
157}