I'm in the process of learning Rust and I have this code:
use std::sync::{Arc, Mutex};
use std::thread::spawn;
pub struct MyText {
my_text: Mutex<Vec<String>>,
}
pub trait MyTextOptions {
fn add(&self, t: String);
}
impl MyTextOptions for MyText {
fn add(&self, text: String) {
let int_text = Arc::new(self);
let put_into_my_text = spawn(move || {
let mut text_feed = int_text.my_text.lock().unwrap();
text_feed.push(text)
});
put_into_my_text.join();
}
}
When I try to run it I get:
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
--> src\buffer.rs:37:33
|
37 | let int_text = Arc::new(self);
| ^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 36:5...
--> src\buffer.rs:36:5
|
36 | / fn add(&self, text: String) {
37 | | let int_text = Arc::new(self);
38 | | let put_into_my_text = spawn(move || {
39 | | let mut text_feed = int_text.my_text.lock().unwrap();
... |
42 | | put_into_my_text.join();
43 | | }
| |_____^
= note: ...so that the expression is assignable:
expected &buffer::MyText
found &buffer::MyText
= note: but, the lifetime must be valid for the static lifetime...
note: ...so that the type `[closure@src\buffer.rs:38:38: 41:10 int_text:std::sync::Arc<&buffer::MyText>, text:std::string::String]` will meet its required lifetime bounds
--> src\buffer.rs:38:32
|
38 | let put_into_my_text = spawn(move || {
|
I seem to fail to understand the lifetime of variables in rust when using threads. No matter what I do with this function I'm still getting this type of error.
A thread spawned via thread::spawn
can in theory outlive its parent thread. If the child thread could reference data from the parent thread, these reference would dangle (be invalid) when the parent thread stops. This is expressed as a 'static
bound on the closure given to thread::spawn
. The fact that you join
the thread in the same function is not understood by the compiler, so the restriction still holds.
You already tried to use an Arc
(presumably to get around this problem), but you are creating an Arc
of self
which is a reference already. So you are just putting a reference into an Arc
. That value does not satisfy the 'static
bound, that's why you are getting an error.
There are multiple ways to solve this problem, many depend on the overall architecture of your project. One of the easiest ways is to use scoped
from crossbeam
(or specifically, crossbeam_utils
):
use crossbeam_utils::thread;
impl MyTextOptions for MyText {
fn add(&self, text: String) {
thread::scope(|s| {
s.spawn(|_| {
let mut text_feed = self.my_text.lock().unwrap();
text_feed.push(text)
});
}).unwrap();
}
}
This is a fancy helper function that actually lets you borrow values from the parent scope by ensuring the child thread ends before the parent thread does.
Another solution would be to put the MyText
value into an Arc
(notably: by value, not by reference). Then you can clone this Arc
a bunch of times and send it to a new thread. But this means you cannot use methods that take &self
as receiver, but you have to solve it in another way.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With