How to use static lifetimes with threads?

I am currently struggling with a lifetime in Rust (1.0), especially when it comes to passing structures through channels.

How do I get this simple compilation example:

use std::sync::mpsc::{Receiver, Sender}; use std::sync::mpsc; use std::thread::spawn; use std::io; use std::io::prelude::*; struct Message<'a> { text: &'a str, } fn main() { let (tx, rx): (Sender<Message>, Receiver<Message>) = mpsc::channel(); let _handle_receive = spawn(move || { for message in rx.iter() { println!("{}", message.text); } }); let stdin = io::stdin(); for line in stdin.lock().lines() { let message = Message { text: &line.unwrap()[..], }; tx.send(message).unwrap(); } } 

I get:

 error[E0597]: borrowed value does not live long enough --> src/main.rs:23:20 | 23 | text: &line.unwrap()[..], | ^^^^^^^^^^^^^ does not live long enough ... 26 | } | - temporary value only lives until here | = note: borrowed value must be valid for the static lifetime... 

I can see why this is ( line only lives for one iteration of for ), but I cannot figure out how to do it right.

  • Should I, like compiler hints, try to convert &str to &'static str ?
  • Am I losing memory if each row has a 'static lifetime?
  • When should I use 'static ? Is this something I should try to avoid or is this normal?
  • Is there a better way to pass String in structures through pipes?

I apologize for these naive questions. I spent quite a lot of time searching already, but I can’t completely circle around me. Probably my dynamic language background is interfering :)

Aside: &input[..] for converting a String to &str is considered OK? This is the only stable way I could find for this.

+8
rust channel
source share
2 answers

You cannot convert &'a T to &'static T , except for a memory leak. Fortunately, this is not necessary. There is no reason to send borrowed pointers to a stream and keep the lines in the main stream. You do not need lines in the main thread. Just send the lines themselves, i.e. Submit String .

If you need access from multiple threads (and you don’t want to clone), use Arc<String> ( Arc<str> may also work in the future). Thus, the string is split between threads that are correctly split, so that it will be freed exactly when the thread does not use it anymore.

Sending links between threads is unsafe because you never know how long another thread will continue to use it, so you don't know when a loan will expire and an object can be freed. Note that in cloud areas there is no this problem (which are not listed in 1.0, but change as we speak) allow this, but regular, spawn ed threads.

'static is not something you should avoid, it’s completely normal for what it does: meaning that the value lives on throughout the program’s time. But if this is not what you are trying to convey, of course, this is the wrong tool.

+12
source share

Think of it this way: a stream does not have a syntactic lifetime, that is, the stream will not be discarded at the end of the code block where it was created. Whatever data you send to the stream, you must be sure that they will live as long as the stream, which means eternity. Which means 'static .

What could go wrong in your case if the main loop sends a link to the stream and destroys the line before it is processed by the stream. The thread will gain access to invalid memory when working with a string.

One option is to put your lines in some kind of statically placed container, but this will mean that you can never destroy these lines. Generally speaking a bad idea. Another option is to think: does the main branch need a line after reading it? What if the main thread transferred responsibility for the line to the processing thread?

 struct Message { text: String, } 
 for line in stdin.lock().lines() { let message = Message { text: line.unwrap(), }; tx.send(message).unwrap(); } 

Now you transfer ownership (relocation) from the main thread to the handler thread. As you move your value, no links are involved, and no checks for life expectancy are applied anymore.

0
source share

All Articles