2015-05-31 5 views
7

В настоящее время я борюсь со временем жизни в Rust (1.0), особенно когда речь идет о передаче структур через каналы.Как использовать статические времена жизни с потоками?

Как бы я получить этот простой пример компиляции:

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(); 
    } 
} 

я получаю:

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... 

Я могу понять, почему это (line живет только для одной итерации for), но я не может понять, каков правильный способ сделать это.

  • Должен ли я, как подсказки компилятора, попробуйте преобразовать &str в &'static str?
  • Я утечка памяти, если каждая строка будет иметь 'static?
  • Когда я должен использовать 'static в любом случае? Это то, что я должен попытаться избежать или это нормально?
  • Есть ли лучший способ пройти String s в структурах по каналам?

Приносим извинения за эти наивные вопросы. Я потратил довольно много времени на поиски уже, но я не могу полностью обвести вокруг себя. Вероятно, мой динамический языковой фон мешает :)

В стороне: &input[..] для преобразования String в &str считается ОК? Это единственный стабильный способ, который я мог бы найти для этого.

ответ

11

Вы не можете преобразовать &'a T в &'static T, за исключением утечки памяти. К счастью, это совсем не обязательно. Нет причин отправлять заимствованные указатели на поток и держать строки в основном потоке. Вам не нужны строки в основном потоке. Просто отправьте сами линии, то есть отправьте String.

Если доступ из нескольких потоков было необходимо (и вы не хотите, чтобы клонировать), используйте Arc<String> (в будущем, Arc<str> может также работать). Таким образом, строка разделяется между потоками, правильно поделился, так что он будет освобожден именно тогда, когда нить не использует его больше.

Отправка ссылок между потоками небезопасна, потому что вы никогда не знаете, как долго другой поток будет продолжать использовать его, поэтому вы не знаете, когда срок действия займа истекает, и объект может быть освобожден. Обратите внимание, что области с областями не имеют этой проблемы (которые не указаны в 1.0, но меняются по мере того, как мы говорим) это разрешить, но регулярные, spawn ed.

'static Это не то, что вам следует избегать, это прекрасно для того, что он делает: обозначая, что значение живет в течение всего времени работы программы. Но если это не то, что вы пытаетесь передать, конечно, это неправильный инструмент.

+0

О, хорошо. Это простое решение. Замена '& str' на' String' в 'struct' делает трюк. Спасибо, я действительно должен был попробовать это первым. – marekventur