移动Arc Mutex Ncurses窗口向下线程仍然无法实现发送

时间:2015-06-11 06:36:36

标签: concurrency rust ncurses

我正在为我正在做的一件小事建立一个ncurses界面。对于输入,我想读它非阻塞。我想我可以将WINDOW包装在Arc Mutex中,但这似乎不起作用,因为它仍然抱怨发送。这是因为ncurses的实现不安全吗?我怎么解决这个问题?理想情况下,我有一个回调而不是tx的工作,所以我可以从堆栈的视图中删除依赖,但我无法将该闭包发送到。

我正在使用此库:https://github.com/jeaye/ncurses-rs

简化代码:

pub struct View {
    max_x: i32,
    max_y: i32,
    messages_window: WINDOW,
    input_window: Arc<Mutex<WINDOW>>
}

pub fn init(&mut self, input_tx: mpsc::Sender<DispatchMessage>) {
        let input_window = self.input_window.clone();
        thread::spawn(move || {
            loop {
                let input_window = input_window.lock().unwrap();
                draw_prompt(input_window);
                let input = prompt_input(input_window);
                input_tx.send(input_to_message(input)).unwrap();
            }
        });
}

fn prompt_input(input: WINDOW) -> String {
    let mut string = String::new();
    wgetstr(input, &mut string);
    string
}

fn draw_prompt(input: WINDOW) {
    wclear(input);
    let top = 0 as chtype;
    let bottom = ' ' as chtype;
    let empty = ' ' as chtype;
    wborder(input, empty,empty,top,bottom,empty,empty,empty,empty);
    mvwprintw(input, 1, 1, ">> ");
    wrefresh(input);
}

我得到的错误:

src/view.rs:40:33: 40:45 error: mismatched types:
 expected `*mut ncurses::ll::WINDOW_impl`,
    found `std::sync::mutex::MutexGuard<'_, *mut ncurses::ll::WINDOW_impl>`
(expected *-ptr,
    found struct `std::sync::mutex::MutexGuard`) [E0308]
src/view.rs:40                     draw_prompt(input_window);
                                               ^~~~~~~~~~~~
note: in expansion of closure expansion
src/view.rs:37:27: 44:14 note: expansion site
src/view.rs:40:33: 40:45 help: run `rustc --explain E0308` to see a detailed explanation
src/view.rs:41:46: 41:58 error: mismatched types:
 expected `*mut ncurses::ll::WINDOW_impl`,
    found `std::sync::mutex::MutexGuard<'_, *mut ncurses::ll::WINDOW_impl>`
(expected *-ptr,
    found struct `std::sync::mutex::MutexGuard`) [E0308]
src/view.rs:41                     let input = prompt_input(input_window);
                                                            ^~~~~~~~~~~~
note: in expansion of closure expansion
src/view.rs:37:27: 44:14 note: expansion site
src/view.rs:41:46: 41:58 help: run `rustc --explain E0308` to see a detailed explanation
src/view.rs:37:13: 37:26 error: the trait `core::marker::Send` is not implemented for the type `*mut ncurses::ll::WINDOW_impl` [E0277]
src/view.rs:37             thread::spawn(move || {
                           ^~~~~~~~~~~~~
src/view.rs:37:13: 37:26 note: `*mut ncurses::ll::WINDOW_impl` cannot be sent between threads safely
src/view.rs:37             thread::spawn(move || {
                           ^~~~~~~~~~~~~
error: aborting due to 3 previous errors

手动解除引用窗口会删除类型错误,但我想我会留下它,因为它可能表明错误。

1 个答案:

答案 0 :(得分:4)

Arc<T>实施Send,其中T同时实现SendSyncMutex<T>实现了SendSync,其中T实现了Send。因此,如果Arc<Mutex<T>>实现SendT只会实现Send。请记住,Send表示“能够跨线程边界传输的类型。”Arc<Mutex<T>>允许从多个线程访问其内容,纯粹处理所有权和可变性问题,因此如果基础类型无法传输跨越线程边界它将无济于事。您可能需要从一个线程执行所有ncurses操作。

Raw pointers明确地不实现Send,因为无法保证它。您可以在其上构造明确实现Send的类型,从而保证所包含的原始指针实际上对于跨线程边界传输是安全的。