As discussed in another topic
- I have code that constructs
impl Fn
s by composingimpl Fn
s - These are executed on multiple threads (via
rayon
) - I'm trying to replace these with
dyn Fn
s.
This has led me to replace lots of impl Fn(A) -> B + Send + Sync
with Arc<dyn Fn(A) -> B + Send + Sync>
, which is seems to be going OK until I have to deal with a closure which borrows a large lookup table: putting this closure in an Arc
requires that the table have 'static
lifetime.
My gut reaction is to try to solve this with scoped threads, and I found build_scoped
and spawn_handler
in rayon
, but I didn't manage to get it to work with those.
Putting rayon
aside and trying to use standard scoped threads as a stepping stone on the way to the real solution, and throwing out most of my domain-specific noise, I end up with this minimal example (need_shared_thing
and run_it
reflect the structure of my real code ... which may well need improving, but that's the context in which I'm trying to make progress at the moment)
use std::sync::Arc;
type Shared = std::collections::HashMap<Input, Output>;
type Input = usize;
type Output = i32;
fn main() {
let shared_thing: Shared = std::collections::HashMap::new();
let _out: Output = std::thread::scope(|s| {
s.spawn(|| run_it(Arc::new(need_shared_thing(&shared_thing))))
}).join().unwrap();
}
fn need_shared_thing(shared: &Shared) -> impl Fn(Input) -> Output + '_ {
|i| *shared.get(&i).unwrap()
}
fn run_it(_: Arc<dyn Fn(Input) -> Output>) -> Output { todo!() }
(playground) which gives this compilation error
Compiling playground v0.0.1 (/playground)
error: lifetime may not live long enough
--> src/main.rs:11:9
|
10 | let _out: Output = std::thread::scope(|s| {
| -- return type of closure is ScopedJoinHandle<'2, i32>
| |
| has type `&'1 Scope<'1, '_>`
11 | s.spawn(|| run_it(Arc::new(need_shared_thing(&shared_thing))))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'2`
and mapping the message's lifetimes to those described in the last section of this page would give
-
'1
->'scope
-
'2
->'env
I'm failing to spot why returning the underlined value would require that 'scope
outlive 'env
. Probably because I've been working on the broader problem for too long by now, and I'm worried that I took a wrong turn somewhere along the way and might well be barking up the wrong tree altogether.