pub unsafe fn fork_map<F, R>(func: F) -> Result<R>
Expand description
Forks, and runs function F in a child process. Waits for the child to terminate and returns the result of F.
§Example
use fork_map::fork_map;
// Result type needs to implement serde::Serialize and serde::Deserialize
pub fn do_with_fork(value: u64) -> u64 {
// Spawn a child process with a copy-on-write copy of memory
unsafe {
fork_map(|| {
// Do some obnoxious operation with `value`
// * Maybe it leaks memory
// * Maybe it uses static resources unsafely and
// prevents multi-threaded operation
// * Maybe you couldn't figure out how to
// send your data to a thread
Ok(value * 10)
}).unwrap()
// Execution continues after the child process has exited
}
}
Often used in conjunction with rayon
since fork_map
will block until the child terminates,
so you can construct a worker pool where each job is executed in a child process:
§Example
use fork_map::fork_map;
use rayon::prelude::*;
pub fn main() {
let my_big_list = [ /* ... */ ];
// Create a worker pool with rayon's into_par_iter
let results = my_big_list.into_par_iter().map(|item| {
// Have each worker spawn a child process for the
// operations we don't want polluting the parent's memory
unsafe {
fork_map(|| {
// Do your ugly operations here
Ok(item * 1234)
}).expect("fork_map succeeded")
}
}).collect::<Vec<_>>();
// Use results here
}
§Safety
Due to the nature of fork()
, this function is very unsound and likely violates most of Rust’s
guarantees about lifetimes, considering all of your memory gets duplicated into a second
process, even though it calls exit(0)
after your closure is executed. Any threads other than
the one calling fork_map
will not be present in the new process, so threaded lifetime
guarantees are also violated. Don’t even think about using async executors with this.