recoverable_spawn/thread/sync/
fn.rs

1use super::*;
2use crate::*;
3
4/// Executes a recoverable function within a panic-safe context.
5///
6/// - `func`: A function implementing the `RecoverableFunction` trait.
7/// - Returns: A `SyncSpawnResult` indicating the success or failure of the function execution.
8pub fn run_function<F: RecoverableFunction>(func: F) -> SyncSpawnResult {
9    set_hook(Box::new(move |_| {}));
10    std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
11        func();
12    }))
13}
14
15/// Executes an error-handling function with a given error message within a panic-safe context.
16///
17/// - `func`: A function implementing the `ErrorHandlerFunction` trait.
18/// - `error`: A string slice representing the error message.
19/// - Returns: A `SyncSpawnResult` indicating the success or failure of the error-handling function execution.
20pub fn run_error_handle_function<E: ErrorHandlerFunction>(func: E, error: &str) -> SyncSpawnResult {
21    set_hook(Box::new(move |_| {}));
22    std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
23        func(error);
24    }))
25}
26
27/// Converts a panic-captured error value into a string.
28///
29/// - `err`: The captured error value, of type `SpawnError`.
30/// - Returns: A string representation of the error value.
31pub fn spawn_error_to_string(err: &SpawnError) -> String {
32    match err.downcast_ref::<&str>() {
33        Some(str_slice) => str_slice.to_string(),
34        None => match err.downcast_ref::<String>() {
35            Some(string) => string.to_owned(),
36            None => format!("{:?}", err),
37        },
38    }
39}
40
41/// Spawns a new thread to run the provided function `function` in a recoverable manner.
42/// If the function `function` panics during execution, the panic will be caught, and the thread
43/// will terminate without crashing the entire program.
44///
45/// # Parameters
46/// - `function`: A function of type `function` to be executed in the spawned thread. It must implement `FnOnce()`, `Send`, `Sync`, and `'static` traits.
47///     - `FnOnce()`: The function is callable with no arguments and no return value.
48///     - `Send`: The function can be safely transferred across thread boundaries.
49///     - `Sync`: The function can be shared across threads safely.
50///     - `'static`: The function does not contain references to non-static data (i.e., data that lives beyond the function's scope).
51///
52/// # Returns
53/// - A `SyncSpawnResult`
54///
55/// # Panics
56/// - This function itself will not panic, but the function `function` could panic during execution.
57///   The panic will be caught, preventing the program from crashing.
58pub fn recoverable_spawn<F>(function: F) -> SyncSpawnResult
59where
60    F: RecoverableFunction,
61{
62    run_function(function)
63}
64
65/// Spawns a recoverable function with an error-handling function in a new thread.
66///
67/// - `function`: The primary function to execute, implementing the `RecoverableFunction` trait.
68/// - `error_handle_function`: A function to handle errors, implementing the `ErrorHandlerFunction` trait.
69/// - Returns: A `SyncSpawnResult`
70pub fn recoverable_spawn_catch<F, E>(function: F, error_handle_function: E) -> SyncSpawnResult
71where
72    F: RecoverableFunction,
73    E: ErrorHandlerFunction,
74{
75    let run_result: SyncSpawnResult = run_function(function);
76    if let Err(err) = run_result.as_ref() {
77        let err_string: String = spawn_error_to_string(err);
78        let _: SyncSpawnResult = run_error_handle_function(error_handle_function, &err_string);
79    }
80    return run_result;
81}
82
83pub fn recoverable_spawn_catch_finally<F, E, L>(
84    function: F,
85    error_handle_function: E,
86    finally: L,
87) -> SyncSpawnResult
88where
89    F: RecoverableFunction,
90    E: ErrorHandlerFunction,
91    L: RecoverableFunction,
92{
93    let run_result: SyncSpawnResult = run_function(function);
94    if let Err(err) = run_result.as_ref() {
95        let err_string: String = spawn_error_to_string(err);
96        let _: SyncSpawnResult = run_error_handle_function(error_handle_function, &err_string);
97    }
98    let _: SyncSpawnResult = run_function(finally);
99    return run_result;
100}