Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rust Lifetimes with mpsc::Sender<T<'a>> and threads

I'm creating a multi-threaded application where I create a receiving channel and a structure to hold the sending channel (to be used later by the implementation). However, the type I'm sending through the channel has a lifetime specification. This type is websocket::message:Message from the rusts-weboscket library. Because of this specification, rust can't seem to correctly infer lifetimes when it gets passed through a thread.

Here's a rust playground example of this error: https://play.rust-lang.org/?gist=7e37547d1c811185654f10a6a461e1ef&version=stable&backtrace=1

Now, I have tried using crossbeam to scope the lifetime, and this seems to solve that immediate issue, but in practically just delegates the lifetime specification issue somewhere else.

In my code I get the error:

   $ cargo check
   Compiling rump v0.1.0 (file:///home/alainh/UPenn/CIS198/Rump)
transport.rs:200:42: 200:57 error: cannot infer an appropriate lifetime for autoref due to conflicting requirements [E0495]
transport.rs:200         self.sender.send(self.serializer.encode(message));
                                                          ^~~~~~~~~~~~~~~
transport.rs:199:5: 202:6 help: consider using an explicit lifetime parameter as shown: fn send<T: Encodable>(&'a mut self, message: &T) -> WampResult<()>
transport.rs:199     fn send<T: Encodable>(&mut self, message: &T) -> WampResult<()> {
transport.rs:200         self.sender.send(self.serializer.encode(message));
transport.rs:201         Ok(())
transport.rs:202     }
error: aborting due to previous error
Could not compile `rump`.

The line in question is this one: https://github.com/aehernandez/Rump/blob/ad717c7ef11857e94d0e1c02539667c8034676c4/src/transport.rs#L199

At this point I'm unsure how to exactly solve this lifetime issue. I don't want to keep delegating it somewhere else. Is there a good solution to this?

like image 350
alainh Avatar asked Oct 19 '22 12:10

alainh


1 Answers

When you spawn a thread it can potentially live forever; certainly outliving your Transport<'a> type for any lifetime 'a other than 'static (the error messages are very confusing though). When you call thread::spawn with a closure, that closure must have the 'static lifetime, which is only true if 'a == 'static.

As you are not actually sending an object with a lifetime across the channel, consider using the 'static lifetime explicitly:

impl Connector for Transport<'static> {
    ...
}

Playpen

Edit:

Manually annotating the types for the sender and receiver

    let (tx, rx): (mpsc::Sender<Message<'a>>, mpsc::Receiver<Message<'a>>) = mpsc::channel();
    let tx_send: mpsc::Sender<Message<'a>> = tx.clone();

shows you a much more sensible error

<anon>:27:22: 27:35 error: the type `[closure@<anon>:27:36: 29:10 tx_send:std::sync::mpsc::Sender<Message<'a>>]` does not fulfill the required lifetime [E0477]
<anon>:27         let handle = thread::spawn(move || {
                               ^~~~~~~~~~~~~
note: type must outlive the static lifetime
error: aborting due to previous error
playpen: application terminated with error code 101

Playpen

like image 158
Djzin Avatar answered Oct 21 '22 05:10

Djzin