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?