recoverable_spawn/thread/
sync.rs

1use super::{r#trait::*, r#type::*};
2use std::thread::{spawn, JoinHandle};
3
4/// Executes a recoverable function within a panic-safe context.
5///
6/// - `func`: A function implementing the `RecoverableFunction` trait.
7/// - Returns: A `SpawnResult` indicating the success or failure of the function execution.
8#[inline]
9pub fn run_function<F: RecoverableFunction>(func: F) -> SpawnResult {
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 `SpawnResult` indicating the success or failure of the error-handling function execution.
20#[inline]
21pub fn run_error_handle_function<E: ErrorHandlerFunction>(func: E, error: &str) -> SpawnResult {
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 `BoxAnySend`.
30/// - Returns: A string representation of the error value.
31#[inline]
32pub fn spawn_error_to_string(err: BoxAnySend) -> String {
33    match err.downcast_ref::<&str>() {
34        Some(str_slice) => str_slice.to_string(),
35        None => match err.downcast_ref::<String>() {
36            Some(string) => string.to_owned(),
37            None => format!("{:?}", err),
38        },
39    }
40}
41
42/// Spawns a new thread to run the provided function `function` in a recoverable manner.
43/// If the function `function` panics during execution, the panic will be caught, and the thread
44/// will terminate without crashing the entire program.
45///
46/// # Parameters
47/// - `function`: A function of type `function` to be executed in the spawned thread. It must implement `FnOnce()`, `Send`, `Sync`, and `'static` traits.
48///     - `FnOnce()`: The function is callable with no arguments and no return value.
49///     - `Send`: The function can be safely transferred across thread boundaries.
50///     - `Sync`: The function can be shared across threads safely.
51///     - `'static`: The function does not contain references to non-static data (i.e., data that lives beyond the function's scope).
52///
53/// # Returns
54/// - A `JoinHandle<()>` representing the spawned thread. The thread can be joined later to wait for its completion.
55///
56///
57/// # Panics
58/// - This function itself will not panic, but the function `function` could panic during execution.
59///   The panic will be caught, preventing the program from crashing.
60#[inline]
61pub fn recoverable_spawn<F>(function: F) -> JoinHandle<()>
62where
63    F: RecoverableFunction,
64{
65    spawn(|| {
66        let _: SpawnResult = run_function(function);
67    })
68}
69
70/// Spawns a recoverable function with an error-handling function in a new thread.
71///
72/// - `function`: The primary function to execute, implementing the `RecoverableFunction` trait.
73/// - `error_handle_function`: A function to handle errors, implementing the `ErrorHandlerFunction` trait.
74/// - Returns: A `JoinHandle<()>` that can be used to manage the spawned thread.
75#[inline]
76pub fn recoverable_spawn_catch<F, E>(function: F, error_handle_function: E) -> JoinHandle<()>
77where
78    F: RecoverableFunction,
79    E: ErrorHandlerFunction,
80{
81    spawn(|| {
82        let run_result: SpawnResult = run_function(function);
83        if let Err(err) = run_result {
84            let err_string: String = spawn_error_to_string(err);
85            let _: SpawnResult = run_error_handle_function(error_handle_function, &err_string);
86        }
87    })
88}
89
90#[inline]
91pub fn recoverable_spawn_catch_finally<F, E, L>(
92    function: F,
93    error_handle_function: E,
94    finally: L,
95) -> JoinHandle<()>
96where
97    F: RecoverableFunction,
98    E: ErrorHandlerFunction,
99    L: RecoverableFunction,
100{
101    spawn(|| {
102        let run_result: SpawnResult = run_function(function);
103        if let Err(err) = run_result {
104            let err_string: String = spawn_error_to_string(err);
105            let _: SpawnResult = run_error_handle_function(error_handle_function, &err_string);
106        }
107        let _: SpawnResult = run_function(finally);
108    })
109}