thread_panic_restart/thread/
spawn.rs

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