我想在并发程序中使用rustbox库。
但是,rustbox::RustBox没有实现Send特性,因此我无法在线程之间共享对象。

extern crate rustbox;

use std::thread;
use std::sync::{ self, Arc, Mutex };
use std::default::Default;

fn main() {
    let rustbox = match rustbox::RustBox::init(Default::default())  {
        Ok(r) => r,
        _ => panic!(""),
    };

    let count = Arc::new(Mutex::new(0usize));
    let (tx, rx) = sync::mpsc::channel();
    let count_clone = count.clone();
    thread::scoped(move|| {
        loop {
            let _ = rx.recv().unwrap();
            show(&rustbox, count_clone.lock().unwrap().clone());
        }
    });
    loop {
        if let Ok(_) = rustbox.poll_event(false) {
            let mut i = count.lock().unwrap();
            *i += 1;
            show(&rustbox, i.clone());
        } else {
            tx.send(()).unwrap();
        }
    }
}

fn show(rustbox: &rustbox::RustBox, count: usize) {
    use rustbox::Color;
    rustbox.print(1, 1, rustbox::RB_BOLD, Color::Default, Color::Default, &format!("{}", count));
}
tx.send(()).unwrap();将在其他线程中发生。

编译器错误消息是:
src/main.rs:16:5: 16:19 error: the trait `core::marker::Send` is not implemented for the type `rustbox::RustBox` [E0277]
src/main.rs:16     thread::scoped(move|| {
               ^~~~~~~~~~~~~~
src/main.rs:16:5: 16:19 note: `rustbox::RustBox` cannot be sent  between threads safely
src/main.rs:16     thread::scoped(move|| {
               ^~~~~~~~~~~~~~
error: aborting due to previous error
Could not compile `sof`.

最佳答案

由于您使用的是scoped线程,这些线程一定会在rustbox之前消失,因此,如果它是Sync,则可以简单地共享对rustbox的引用。

fn main() {
    let rustbox = match rustbox::RustBox::init(Default::default())  {
        Ok(r) => r,
        _ => panic!(""),
    };
    let rustbox = &rustbox;

    let count = Arc::new(Mutex::new(0usize));
    let (tx, rx) = sync::mpsc::channel();
    let count_clone = count.clone();
    thread::scoped(move|| {
        loop {
            let _ = rx.recv().unwrap();
            show(rustbox, count_clone.lock().unwrap().clone());
        }
    });
    loop {
        if let Ok(_) = rustbox.poll_event(false) {
            let mut i = count.lock().unwrap();
            *i += 1;
            show(rustbox, i.clone());
        } else {
            tx.send(()).unwrap();
        }
    }
}

如果不是Sync,则只需将其包装在Mutex中并共享对此的引用。

注意:这仅是可能的,因为您使用的是thread::scoped,如果您使用的是thread::spawned,那么Send将是必需的。

10-04 18:38