recoverable_spawn/thread/run.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
use std::any::Any;
use std::panic::{self, AssertUnwindSafe};
use std::sync::{Arc, RwLock};
use std::thread::{spawn, JoinHandle};
/// Spawns a new thread to run the provided function `f` in a recoverable manner.
/// If the function `f` panics during execution, the panic will be caught, and the thread
/// will terminate without crashing the entire program.
///
/// # Parameters
/// - `f`: A function of type `F` to be executed in the spawned thread. It must implement `Fn()`, `Send`, `Sync`, and `'static` traits.
/// - `Fn()`: The function is callable with no arguments and no return value.
/// - `Send`: The function can be safely transferred across thread boundaries.
/// - `Sync`: The function can be shared across threads safely.
/// - `'static`: The function does not contain references to non-static data (i.e., data that lives beyond the function's scope).
///
/// # Returns
/// - A `JoinHandle<()>` representing the spawned thread. The thread can be joined later to wait for its completion.
///
///
/// # Panics
/// - This function itself will not panic, but the function `f` could panic during execution.
/// The panic will be caught, preventing the program from crashing.
#[inline]
pub fn recoverable_spawn<F>(f: F) -> JoinHandle<()>
where
F: Fn() + Send + Sync + 'static,
{
let f: Arc<RwLock<F>> = Arc::new(RwLock::new(f));
spawn(move || {
let _: Result<(), Box<dyn Any + Send>> = panic::catch_unwind(AssertUnwindSafe({
let f: Arc<RwLock<F>> = Arc::clone(&f);
move || {
if let Ok(func) = f.read() {
func();
}
}
}));
})
}