2017-10-20 79 views
1

我是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 

如何实现SyncRustBox类型,这样上面的代码可以工作?

+1

你懂的特点['Send'和'Sync'(https://doc.rust-lang.org/book/第二版/ ch16-04伸长并发同步和 - send.html)?最好你了解类型不是“同步”的含义。一个不只是实现'Sync'。相关问题: https://stackoverflow.com/q/36649865/1233251 –

回答

1

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 { 
// ... 
} 
+0

嗨,谢谢你的回应!我按照你的说法尝试过,它似乎确实与(现在)未合并的公关合作。不过,我也试过不使用助手变量'pe',但它完全忽略了我按下的任何输入键。为什么在这里需要使用助手变量? – ritiek

+2

可悲的是我没有这方面的参考;但'lock()'返回的临时'MutexGuard'只在“当前语句”完成后才会被删除;如果你锁定了'match',它将保持锁定状态直到匹配结束,这意味着它将在匹配内调用的'mark_at'中死锁。用'let'语句锁定在'let'后面。 – Stefan

+0

在https://play.rust-lang.org/?gist=94690e7a2bec2c6b11b26c50fd3d9c3c&version=stable中自己查看一下 - 我通过登录'lock()'和'Drop'伪造了一个Mutex实现。 – Stefan