Compiling foo v0.1.0 (/Users/gecko/code/foo)
error[E0597]: `a` does not live long enough
--> src/main.rs:14:28
|
14 | tokio::task::spawn(foo(&a)).await?;
| ----^^-
| | |
| | borrowed value does not live long enough
| argument requires that `a` is borrowed for `'static`
...
17 | }
| - `a` dropped here while still borrowed
Since I'm awaiting the task, it seems at last to me that the reference lives long enough, don't?
Is there a way to tell the borrow checker that? Hey the future will be awaited before the referece is dropped,
Does async move {} blocks awaits expect 'static lifetime? it seems that I'm missing something here ....
task::spawn is conceptually same as thread::spawn. They require 'static lifetime because the newly spawned task/thread may live longer than the current task/thread.
Translating your code into threaded version would make understand easier:
std::thread::spawn(foo(&a)).join()?;
You spawn the task/thread and immediately await/join on it, does it make sense?
The sample doesn't make lots of sense, in practice I have something like this
let t1 = tokio::task::spawn(foo(&a));
let t2 = tokio::task::spawn(bar(&a));
// a "main loop" doing all kinds of stuff
// oops something happens, signal tasks to exit
t1.await?
t2.await?
Basically each task is a loop that read stuff and send to main thread through a channel, I have a configuration file, that becomes a Config struct that I want to share between tasks, this Config is what I'm trying to pass as a reference.
newly spawned task/thread may live longer than the current task/thread.
I see the main task is my misconception here, do I need something like an Arc so?
You can't do that since tokio::task::spawn only takes 'static tasks, as the compiler tells you.
The preferred solution is to use Future::join instead of spawning (and join both those futures plus the "main loop" future); alternatively you need something like the async-scoped crate (or you could unsafely transmute to 'static, but that's obviously unsafe and inelegant).
Sorry, you can't put references into tokio::spawn. Perhaps you want the join! macro instead, as it allows running things concurrently while allowing references. You can also share the object using an Arc instead of a reference.
In this case I want to tasks to run apart from one each other, if some task hangs I want others to keep going on ... so I think that the way to go is using an Arc, thanks again!
For a matter of completeness here is how the code looks with Arc