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}