在线程下移动 Arc Mutex Ncurses window 仍然没有实现发送

Moving Arc Mutex Ncurses window down thread still doesn't implement send

我正在为我正在做的一件小事构建一个 ncurses 界面。对于输入,我想非阻塞地读取它。我想我可以将 WINDOW 包装在 Arc Mutex 中,但这似乎不起作用,因为它仍然抱怨发送。这是因为ncurses的实现不安全吗?我该如何解决这个问题?理想情况下,我会使用回调而不是 tx 来完成这项工作,这样我就可以从堆栈的视图中删除依赖性,但我也无法将闭包发送给 Send。

我正在使用这个库: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

手动解除对 window 的引用可以消除类型错误,但我认为我会保留它,因为它可能表明出了什么问题。

Arc<T> 实现了 Send,其中 T 实现了 SendSyncMutex<T> 实现 SendSync,其中 T 实现 Send。所以 Arc<Mutex<T>> 仅在 T 实现 Send 时才实现 Send。请记住,Send 表示“能够跨线程边界传输的类型”。 Arc<Mutex<T>> 允许从多个线程访问它的内容,纯粹处理所有权和可变性问题,所以如果底层类型不能跨线程边界传输,它也无济于事。您可能需要从一个线程执行所有 ncurses 操作。

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