recoverable_spawn/thread/async.rs
1use super::{r#trait::*, r#type::*};
2use once_cell::sync::Lazy;
3use runtime::Runtime;
4use std::sync::Arc;
5use std::thread::{spawn, JoinHandle};
6use task::JoinError;
7use tokio::*;
8
9static GLOBAL_RUNTIME: Lazy<Runtime> = Lazy::new(|| loop {
10 match Runtime::new() {
11 Ok(runtime) => return runtime,
12 Err(_) => {}
13 }
14});
15
16/// Executes a recoverable function within a panic-safe context.
17///
18/// - `func`: A function implementing the `AsyncRecoverableFunction` trait.
19/// - Returns: A `AsyncSpawnResult` indicating the success or failure of the function execution.
20#[inline]
21pub fn run_function<F: AsyncRecoverableFunction>(func: F) -> AsyncSpawnResult {
22 let res: Result<(), JoinError> = GLOBAL_RUNTIME.block_on(async move {
23 let func = async move {
24 func.call().await;
25 };
26 return tokio::spawn(func).await;
27 });
28 return res;
29}
30
31/// Executes an error-handling function with a given error message within a panic-safe context.
32///
33/// - `func`: A function implementing the `AsyncErrorHandlerFunction` trait.
34/// - `error`: A string slice representing the error message.
35/// - Returns: A `AsyncSpawnResult` indicating the success or failure of the error-handling function execution.
36#[inline]
37pub fn run_error_handle_function<E: AsyncErrorHandlerFunction>(
38 func: E,
39 error: Arc<String>,
40) -> AsyncSpawnResult {
41 let res: Result<(), JoinError> = GLOBAL_RUNTIME.block_on(async move {
42 let func = async move {
43 func.call(error.clone()).await;
44 };
45 return tokio::spawn(func).await;
46 });
47 return res;
48}
49
50/// Executes a recoverable function within a panic-safe context.
51///
52/// - `func`: A function implementing the `AsyncRecoverableFunction` trait.
53/// - Returns: A `AsyncSpawnResult` indicating the success or failure of the function execution.
54#[inline]
55pub async fn async_run_function<F: AsyncRecoverableFunction>(func: F) -> AsyncSpawnResult {
56 let func = async move {
57 func.call().await;
58 };
59 return tokio::spawn(func).await;
60}
61
62/// Executes an error-handling function with a given error message within a panic-safe context.
63///
64/// - `func`: A function implementing the `AsyncErrorHandlerFunction` trait.
65/// - `error`: A string slice representing the error message.
66/// - Returns: A `AsyncSpawnResult` indicating the success or failure of the error-handling function execution.
67#[inline]
68pub async fn async_run_error_handle_function<E: AsyncErrorHandlerFunction>(
69 func: E,
70 error: Arc<String>,
71) -> AsyncSpawnResult {
72 let func = async move {
73 func.call(error.clone()).await;
74 };
75 return tokio::spawn(func).await;
76}
77
78/// Converts a panic-captured error value into a string.
79///
80/// - `err`: The captured error value, of type `JoinError `.
81/// - Returns: A string representation of the error value.
82#[inline]
83pub fn tokio_error_to_string(err: JoinError) -> String {
84 err.to_string()
85}
86
87/// Spawns a new thread to run the provided function `function` in a recoverable manner.
88/// If the function `function` panics during execution, the panic will be caught, and the thread
89/// will terminate without crashing the entire program.
90///
91/// # Parameters
92/// - `function`: A function of type `function` to be executed in the spawned thread. It must implement `FnOnce()`, `Send`, `Sync`, and `'static` traits.
93/// - `FnOnce()`: The function is callable with no arguments and no return value.
94/// - `Send`: The function can be safely transferred across thread boundaries.
95/// - `Sync`: The function can be shared across threads safely.
96/// - `'static`: The function does not contain references to non-static data (i.e., data that lives beyond the function's scope).
97///
98/// # Returns
99/// - A `JoinHandle<()>` representing the spawned thread. The thread can be joined later to wait for its completion.
100///
101///
102/// # Panics
103/// - This function itself will not panic, but the function `function` could panic during execution.
104/// The panic will be caught, preventing the program from crashing.
105#[inline]
106pub fn recoverable_spawn<F>(function: F) -> JoinHandle<()>
107where
108 F: AsyncRecoverableFunction,
109{
110 spawn(|| {
111 let _: AsyncSpawnResult = run_function(function);
112 })
113}
114
115/// Spawns a new thread to run the provided function `function` in a recoverable manner.
116/// If the function `function` panics during execution, the panic will be caught, and the thread
117/// will terminate without crashing the entire program.
118///
119/// # Parameters
120/// - `function`: A function of type `function` to be executed in the spawned thread. It must implement `FnOnce()`, `Send`, `Sync`, and `'static` traits.
121/// - `FnOnce()`: The function is callable with no arguments and no return value.
122/// - `Send`: The function can be safely transferred across thread boundaries.
123/// - `Sync`: The function can be shared across threads safely.
124/// - `'static`: The function does not contain references to non-static data (i.e., data that lives beyond the function's scope).
125///
126/// # Returns
127/// - A `JoinHandle<()>` representing the spawned thread. The thread can be joined later to wait for its completion.
128///
129///
130/// # Panics
131/// - This function itself will not panic, but the function `function` could panic during execution.
132/// The panic will be caught, preventing the program from crashing.
133#[inline]
134pub async fn async_recoverable_spawn<F>(function: F)
135where
136 F: AsyncRecoverableFunction,
137{
138 let _ = async_run_function(function).await;
139}
140
141/// Spawns a recoverable function with an error-handling function in a new thread.
142///
143/// - `function`: The primary function to execute, implementing the `AsyncRecoverableFunction` trait.
144/// - `error_handle_function`: A function to handle errors, implementing the `AsyncErrorHandlerFunction` trait.
145/// - Returns: A `JoinHandle<()>` that can be used to manage the spawned thread.
146#[inline]
147pub fn recoverable_spawn_catch<F, E>(function: F, error_handle_function: E) -> JoinHandle<()>
148where
149 F: AsyncRecoverableFunction,
150 E: AsyncErrorHandlerFunction,
151{
152 spawn(|| {
153 let run_result: AsyncSpawnResult = run_function(function);
154 if let Err(err) = run_result {
155 let err_string: String = tokio_error_to_string(err);
156 let _: AsyncSpawnResult =
157 run_error_handle_function(error_handle_function, Arc::new(err_string));
158 }
159 })
160}
161
162/// Spawns a recoverable function with an error-handling function in a new thread.
163///
164/// - `function`: The primary function to execute, implementing the `AsyncRecoverableFunction` trait.
165/// - `error_handle_function`: A function to handle errors, implementing the `AsyncErrorHandlerFunction` trait.
166#[inline]
167pub async fn async_recoverable_spawn_catch<F, E>(function: F, error_handle_function: E)
168where
169 F: AsyncRecoverableFunction,
170 E: AsyncErrorHandlerFunction,
171{
172 let run_result: AsyncSpawnResult = async_run_function(function).await;
173 if let Err(err) = run_result {
174 let err_string: String = tokio_error_to_string(err);
175 let _: AsyncSpawnResult =
176 async_run_error_handle_function(error_handle_function, Arc::new(err_string)).await;
177 }
178}
179
180/// Spawns an asynchronous recoverable function, catches any errors with an error-handling function,
181/// and ensures that a final function is always executed, regardless of whether an error occurred.
182///
183/// This function runs a series of operations in an asynchronous context, where:
184/// - `function` is executed first. If it results in an error, the `error_handle_function` is called.
185/// - After either the main function or the error handler finishes, the `finally` function is executed.
186/// This guarantees that the `finally` function runs regardless of the success or failure of the main operation.
187///
188/// # Parameters
189/// - `function`: The primary function to execute, which must implement the `AsyncRecoverableFunction` trait.
190/// - `error_handle_function`: A function that handles errors, which must implement the `AsyncErrorHandlerFunction` trait.
191/// - `finally`: A function that will be executed after the main function and error handler, which must implement the `AsyncRecoverableFunction` trait.
192///
193/// # Returns
194/// - A `JoinHandle<()>` that can be used to manage the spawned thread, ensuring that all the functions execute
195/// in a recoverable context and the final block always runs.
196///
197/// # Errors
198/// - If the `function` fails, the `error_handle_function` is invoked. If this fails as well, it will not stop the execution
199/// of the `finally` block.
200/// - The final block (`finally`) is always executed, even if the main function (`function`) or the error handler (`error_handle_function`) fails.
201/// Spawns an asynchronous recoverable function, catches any errors with an error-handling function,
202/// and ensures that a final function is always executed, regardless of whether an error occurred.
203///
204/// This function runs a series of operations in an asynchronous context, where:
205/// - `function` is executed first. If it results in an error, the `error_handle_function` is called.
206/// - After either the main function or the error handler finishes, the `finally` function is executed.
207/// This guarantees that the `finally` function runs regardless of the success or failure of the main operation.
208///
209/// # Parameters
210/// - `function`: The primary function to execute, which must implement the `AsyncRecoverableFunction` trait.
211/// - `error_handle_function`: A function that handles errors, which must implement the `AsyncErrorHandlerFunction` trait.
212/// - `finally`: A function that will be executed after the main function and error handler, which must implement the `AsyncRecoverableFunction` trait.
213///
214/// # Returns
215/// - A `JoinHandle<()>` that can be used to manage the spawned thread, ensuring that all the functions execute
216/// in a recoverable context and the final block always runs.
217///
218/// # Errors
219/// - If the `function` fails, the `error_handle_function` is invoked. If this fails as well, it will not stop the execution
220/// of the `finally` block.
221/// - The final block (`finally`) is always executed, even if the main function (`function`) or the error handler (`error_handle_function`) fails.
222#[inline]
223pub fn recoverable_spawn_catch_finally<F, E, L>(
224 function: F,
225 error_handle_function: E,
226 finally: L,
227) -> JoinHandle<()>
228where
229 F: AsyncRecoverableFunction,
230 E: AsyncErrorHandlerFunction,
231 L: AsyncRecoverableFunction,
232{
233 spawn(|| {
234 let run_result: AsyncSpawnResult = run_function(function);
235 if let Err(err) = run_result {
236 let err_string: String = tokio_error_to_string(err);
237 let _: AsyncSpawnResult =
238 run_error_handle_function(error_handle_function, Arc::new(err_string));
239 }
240 let _: AsyncSpawnResult = run_function(finally);
241 })
242}
243
244/// Spawns an asynchronous recoverable function, catches any errors with an error-handling function,
245/// and ensures that a final function is always executed, regardless of whether an error occurred.
246///
247/// This function runs a series of operations in an asynchronous context, where:
248/// - `function` is executed first. If it results in an error, the `error_handle_function` is called.
249/// - After either the main function or the error handler finishes, the `finally` function is executed.
250/// This guarantees that the `finally` function runs regardless of the success or failure of the main operation.
251///
252/// # Parameters
253/// - `function`: The primary function to execute, which must implement the `AsyncRecoverableFunction` trait.
254/// - `error_handle_function`: A function that handles errors, which must implement the `AsyncErrorHandlerFunction` trait.
255/// - `finally`: A function that will be executed after the main function and error handler, which must implement the `AsyncRecoverableFunction` trait.
256///
257/// # Returns
258/// - A `JoinHandle<()>` that can be used to manage the spawned thread, ensuring that all the functions execute
259/// in a recoverable context and the final block always runs.
260///
261/// # Errors
262/// - If the `function` fails, the `error_handle_function` is invoked. If this fails as well, it will not stop the execution
263/// of the `finally` block.
264/// - The final block (`finally`) is always executed, even if the main function (`function`) or the error handler (`error_handle_function`) fails.
265/// Spawns an asynchronous recoverable function, catches any errors with an error-handling function,
266/// and ensures that a final function is always executed, regardless of whether an error occurred.
267///
268/// This function runs a series of operations in an asynchronous context, where:
269/// - `function` is executed first. If it results in an error, the `error_handle_function` is called.
270/// - After either the main function or the error handler finishes, the `finally` function is executed.
271/// This guarantees that the `finally` function runs regardless of the success or failure of the main operation.
272///
273/// # Parameters
274/// - `function`: The primary function to execute, which must implement the `AsyncRecoverableFunction` trait.
275/// - `error_handle_function`: A function that handles errors, which must implement the `AsyncErrorHandlerFunction` trait.
276/// - `finally`: A function that will be executed after the main function and error handler, which must implement the `AsyncRecoverableFunction` trait.
277///
278/// # Returns
279/// - A `JoinHandle<()>` that can be used to manage the spawned thread, ensuring that all the functions execute
280/// in a recoverable context and the final block always runs.
281///
282/// # Errors
283/// - If the `function` fails, the `error_handle_function` is invoked. If this fails as well, it will not stop the execution
284/// of the `finally` block.
285/// - The final block (`finally`) is always executed, even if the main function (`function`) or the error handler (`error_handle_function`) fails.
286#[inline]
287pub async fn async_recoverable_spawn_catch_finally<F, E, L>(
288 function: F,
289 error_handle_function: E,
290 finally: L,
291) where
292 F: AsyncRecoverableFunction,
293 E: AsyncErrorHandlerFunction,
294 L: AsyncRecoverableFunction,
295{
296 let run_result: AsyncSpawnResult = async_run_function(function).await;
297 if let Err(err) = run_result {
298 let err_string: String = tokio_error_to_string(err);
299 let _: AsyncSpawnResult =
300 async_run_error_handle_function(error_handle_function, Arc::new(err_string)).await;
301 }
302 let _: AsyncSpawnResult = async_run_function(finally).await;
303}