如何实现RustBox的同步?
我是Rust的新主题。我正在努力通过线程内的rustbox箱的RustBox
type。如何实现RustBox的同步?
欲按q钥匙,而且它在显示2秒钟一个+
符号(1,1),而予压瓦特那些2秒内键,其示出了另一+
在(1,2符号)。
我写了相同的逻辑一些代码:
extern crate rustbox;
use std::thread;
use std::time::Duration;
use rustbox::{Color, RustBox};
use rustbox::Key;
fn mark_at(x: usize, y: usize, rustbox: &RustBox) {
rustbox.print(x, y, rustbox::RB_BOLD, Color::Black, Color::White, "+");
thread::spawn(move || {
let delay = Duration::from_millis(2000);
thread::sleep(delay);
rustbox.print(x, y, rustbox::RB_BOLD, Color::Black, Color::White, " ");
});
}
fn main() {
let rustbox = match RustBox::init(Default::default()) {
Result::Ok(v) => v,
Result::Err(e) => panic!("{}", e),
};
rustbox.print(1, 1, rustbox::RB_BOLD, Color::Black, Color::White, " ");
rustbox.print(1, 2, rustbox::RB_BOLD, Color::Black, Color::White, " ");
loop {
rustbox.present();
match rustbox.poll_event(false) {
Ok(rustbox::Event::KeyEvent(key)) => {
match key {
Key::Char('q') => {
mark_at(1, 1, &rustbox);
}
Key::Char('w') => {
mark_at(1, 2, &rustbox);
}
Key::Esc => { break; }
_ => { }
}
},
Err(e) => panic!("{}", e),
_ => { }
}
}
}
它给我:
error[E0277]: the trait bound `*mut(): std::marker::Sync` is not satisfied in `rustbox::RustBox`
--> src/main.rs:12:5
|
12 | thread::spawn(move || {
| ^^^^^^^^^^^^^ `*mut()` cannot be shared between threads safely
|
= help: within `rustbox::RustBox`, the trait `std::marker::Sync` is not implemented for `*mut()`
= note: required because it appears within the type `std::marker::PhantomData<*mut()>`
= note: required because it appears within the type `rustbox::RustBox`
= note: required because of the requirements on the impl of `std::marker::Send` for `&rustbox::RustBox`
= note: required because it appears within the type `[[email protected]/main.rs:12:19: 16:6 rustbox:&rustbox::RustBox, x:usize, y:usize]`
= note: required by `std::thread::spawn`
error: aborting due to previous error
如何实现Sync
为RustBox
类型,这样上面的代码可以工作?
RustBox
没有实现Send
,所以没有(安全)的方式在线程之间共享(好像你已经找到了尚未合并拉请求https://github.com/gchp/rustbox/pull/65这将支持Send
)。
如果合并提取请求,则可以将RustBox
包装为Mutex
,即Mutex<RustBox>
,并且可以在线程之间共享对它的引用。
但是你会遇到一生的问题:你的rustbox
引用不够长,不足以产生一个使用它的新线程,所以你必须把它包装在Arc
。
use std::sync::{Arc,Mutex};
fn mark_at(x: usize, y: usize, rustbox: &Arc<Mutex<RustBox>>) {
rustbox.lock().unwrap().print(x, y, rustbox::RB_BOLD, Color::Black, Color::White, "+");
let rustbox = rustbox.clone(); // increment reference counter
thread::spawn(move || {
let delay = Duration::from_millis(2000);
thread::sleep(delay);
rustbox.lock().unwrap().print(x, y, rustbox::RB_BOLD, Color::Black, Color::White, " ");
});
}
在你main
功能,你必须包裹rustbox
:
let rustbox = Arc::new(Mutex::new(rustbox));
和lock()
它的每一个使用它的时间。
确保你不要把锁保持太久;它可以帮助使用辅助变量,以使这更明确,如:
let pe = rustbox.lock().unwrap().poll_event(false);
match pe {
// ...
}
嗨,谢谢你的回应!我按照你的说法尝试过,它似乎确实与(现在)未合并的公关合作。不过,我也试过不使用助手变量'pe',但它完全忽略了我按下的任何输入键。为什么在这里需要使用助手变量? – ritiek
可悲的是我没有这方面的参考;但'lock()'返回的临时'MutexGuard'只在“当前语句”完成后才会被删除;如果你锁定了'match',它将保持锁定状态直到匹配结束,这意味着它将在匹配内调用的'mark_at'中死锁。用'let'语句锁定在'let'后面。 – Stefan
在https://play.rust-lang.org/?gist=94690e7a2bec2c6b11b26c50fd3d9c3c&version=stable中自己查看一下 - 我通过登录'lock()'和'Drop'伪造了一个Mutex实现。 – Stefan
你懂的特点['Send'和'Sync'(https://doc.rust-lang.org/book/第二版/ ch16-04伸长并发同步和 - send.html)?最好你了解类型不是“同步”的含义。一个不只是实现'Sync'。相关问题: https://stackoverflow.com/q/36649865/1233251 –