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}