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