I'm trying to run CPU-bound computations inside an async context. The recommendation I found is to run the calculation via a parallelism library (e.g., rayon) and send the result through a one-shot channel to the waiting async function. This leads to the code below.
#[derive(Debug)]
struct BigData(usize); // very expensive to clone
async fn foo<'a>(arg: &'a BigData) -> BigData {
let (sender, receiver) = tokio::sync::oneshot::channel();
rayon::spawn(move || {
let argument = arg; // <- ERROR: cannot captured `&'a BigData` here
// Some long blocking computation here
let result = BigData(argument.0);
sender.send(result).unwrap();
});
receiver.await.unwrap()
}
The problem is that the computation references arg, which lasts only for 'a, but the spawn method (rightfully) requires the closure to be 'static. However, here, I know that the closure finishes its execution within 'a since foo won't return until sender.send is invoked (or the closure panic, which can probably be handled with catch_unwind).
Would it be sound to transmute the lifetime somewhere (e.g. extend arg lifetime)? Alternatively, are there other approaches to running a (sync) background task that captures stack variables of a code block, which requires the task completion to continue?