I have a question for you, regarding my 'idx' structure and it's lifetimes... This structure is a cloneable multi threaded object.
This code works, how is it that moving 'idx' one layer up suddenly meant it didn't satify the 'static' lifetime requirement.
main() {
let w = webtask::Webtask::new();
// Wait for threads to finish
}
pub fn new() -> Self {
let (tx, rx) = oneshot::channel();
let mut idx = fastauth::createindex();
idx.load_index("users.dat.idx");
let lookup= warp::path!("lookup" / String).map(move |name| { Webtask::do_lookup(idx.clone(),name) });
let routes = lookup; //hello.or(lookup).or(check);
let (_addr, server) = warp::serve(routes).bind_with_graceful_shutdown(([127, 0, 0, 1], 3030), async {
rx.await.ok();
});
let thread = tokio::task::spawn(server);
Webtask {thread,tx}
}
-------- However, when I try and move 'idx' to the outer layer function I get errors..
main() {
let mut idx = fastauth::createindex();
idx.load_index("users.dat.idx");
let w = webtask::Webtask::new(&idx);
// Here I plan to reuse 'idx' as it's really a global structure that will exist the entire time the program is running...
do_something_else(&idx);
// then wait for threads to finish...
exit_when_done();
}
...
pub fn new<'inf>(idx: &'inf fastauth::Idx) -> Self {
let (tx, rx) = oneshot::channel();
let lookup= warp::path!("lookup" / String).map(move |name| { Webtask::do_lookup(idx.clone(),name) }); // IS CAPTURED HERE
let routes = lookup; //hello.or(lookup).or(check);
let (_addr, server) = warp::serve(routes).bind_with_graceful_shutdown(([127, 0, 0, 1], 3030), async { // IS REQUIRED TO LIVE AS LONG AS STATIC HERE.
rx.await.ok();
});
let thread = tokio::task::spawn(server);
// return our 'w' structure...
Webtask {thread,tx}
}
idx has lifetime 'inf but it needs to satisfy a 'static lifetime requirement
The important lines in the working code are:
Here,
idxhas typefastauth::Idxand is moved inside the closure, so the compiler can guarantee thatidxwill not be destroyed before the closure.In the non-working code:
Here,
idxhas type&fastauth::Idxso it is only a reference. That reference is moved inside the closure, but the realIdxis still outside the closure (in themainfunction), so the compiler can't guarantee that it won't get destroyed before the closure.Depending on the reason why you wanted to move
idxup, you have several solutions:newcan takeidxby value instead of taking it by referencebut that means you won't be able to re-use
idxinmainafter you callnew, so not really a solution for you.You can use reference-counting with
RcorArcRcandArcallow multiple contexts to share ownership of a value, so that the value only gets destroyed when the last reference goes out of scope.You can use
lazy_staticto create a global immutable static valueSee the
lazy_staticcrate for details.