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}