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