我正在为我正在做的一件小事建立一个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
手动解除引用窗口会删除类型错误,但我想我会留下它,因为它可能表明错误。
答案 0 :(得分:4)
Arc<T>
实施Send
,其中T
同时实现Send
和Sync
。 Mutex<T>
实现了Send
和Sync
,其中T
实现了Send
。因此,如果Arc<Mutex<T>>
实现Send
,T
只会实现Send
。请记住,Send
表示“能够跨线程边界传输的类型。”Arc<Mutex<T>>
允许从多个线程访问其内容,纯粹处理所有权和可变性问题,因此如果基础类型无法传输跨越线程边界它将无济于事。您可能需要从一个线程执行所有ncurses操作。
Raw pointers明确地不实现Send
,因为无法保证它。您可以在其上构造明确实现Send
的类型,从而保证所包含的原始指针实际上对于跨线程边界传输是安全的。