Reputation: 234
I am a Rust beginner and I can’t get the following code to compile. I know this problem might be not new, tried searching all over the place but couldn't find a proper answer to the below problem.
Basically i m trying to call methods from thread, and also using different structs for sending and receiving objects between the threads.
use std::{thread, time};
struct SenderStruct;
impl SenderStruct {
fn send(&self, sndr: Sender<(Option<String>)>) {
let count = 0;
loop {
sndr.send(Some(String::from("Hello"))).unwrap();
thread::sleep(time::Duration::from_millis(1000));
count = count + 1;
if count == 50 {
break;
}
}
sndr.send(None);
}
}
struct ReceiveStruct;
impl ReceiveStruct {
fn receive(&self, rec: Receiver<Option<String>>) {
loop {
let recv_out = rec.recv().unwrap();
match recv_out {
Some(some_str) => println!("{}", some_str),
None => break,
}
}
}
}
struct SendReceiveStruct {
m_ss: SenderStruct,
m_sos: ReceiveStruct,
m_recv_hndlr: Option<thread::JoinHandle<()>>,
}
impl SendReceiveStruct {
fn new() -> Self {
SendReceiveStruct {
m_ss: SenderStruct {},
m_sos: ReceiveStruct {},
m_recv_hndlr: None,
}
}
fn start(&mut self) {
let (tx, rx): (Sender<(Option<String>)>, Receiver<Option<String>>) = channel();
thread::spawn(move || self.m_ss.send(tx));
self.m_recv_hndlr = Some(thread::spawn(move || self.m_sos.receive(rx)));
}
fn wait_for_recevier(&mut self) {
self.m_recv_hndlr.unwrap().join();
}
}
fn main() {
println!("Hello, world!");
let mut ubs = SendReceiveStruct::new();
ubs.start();
ubs.wait_for_recevier();
}
But i m getting lifetime issues all over the place
$ cargo build
Compiling threads v0.1.0 (/root/learn-rust/threads)
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
--> src/main.rs:55:23
|
55 | thread::spawn(move || self.m_ss.send(tx));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 52:5...
--> src/main.rs:52:5
|
52 | / fn start(&mut self) {
53 | | let (tx, rx): (Sender<(Option<String>)>, Receiver<Option<String>>) = channel();
54 | |
55 | | thread::spawn(move || self.m_ss.send(tx));
56 | | self.m_recv_hndlr = Some(thread::spawn(move || self.m_sos.receive(rx)));
57 | | }
| |_____^
= note: ...so that the types are compatible:
expected &mut SendReceiveStruct
found &mut SendReceiveStruct
= note: but, the lifetime must be valid for the static lifetime...
note: ...so that the type `[closure@src/main.rs:55:23: 55:49 self:&mut SendReceiveStruct, tx:std::sync::mpsc::Sender<std::option::Option<std::string::String>>]` will meet its required lifetime bounds
--> src/main.rs:55:9
|
55 | thread::spawn(move || self.m_ss.send(tx));
Any pointers (or other references) would really help, and also any other possible approaches for the above problem ?
Upvotes: 0
Views: 3555
Reputation: 13942
If you examine the signature of std::thread::spawn
:
pub fn spawn<F, T>(f: F) -> JoinHandle<T>
where
F: FnOnce() -> T,
F: Send + 'static,
T: Send + 'static,
and its documentation closely:
The
'static
constraint means that the closure and its return value must have a lifetime of the whole program execution. The reason for this is that threads can detach and outlive the lifetime they have been created in.
However, the &mut self
value closure closes over may not live long enough. One way to overcome that is to clone the value the closure actually uses:
#[derive(Clone)]
struct SenderStruct;
#[derive(Clone)]
struct ReceiveStruct;
impl SendReceiveStruct {
fn start(&mut self) {
let (tx, rx): (Sender<Option<String>>, Receiver<Option<String>>) = channel();
thread::spawn({
let ss = self.m_ss.clone();
move || ss.send(tx)
});
self.m_recv_hndlr = Some(thread::spawn({
let sos = self.m_sos.clone();
move || sos.receive(rx)
}));
}
fn wait_for_recevier(&mut self) {
self.m_recv_hndlr.take().unwrap().join();
}
}
Except for several other minor issues, your code now compiles.
Upvotes: 4