2017-10-20 2 views
1

私はRustのスレッドに新しいです。スレッド内のrustbox枠のRustBox typeを渡すのに苦労しています。RustBoxの同期を実装する方法は?

IがI(1における別の+シンボルを示し、それら2秒以内 Wキー、2を押しながら(1、1)Qキーを押すと、それがで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 

上記のコードは、仕事ができるように、どのように私はRustBoxタイプにSyncを実装していますか?

+1

あなたは(特性[ 'Send'と' Sync']を理解していますhttps://doc.rust-lang.org/book/ second-edition/ch16-04-extensible-concurrency-sync-and-send.html)?あなたが 'Sync'ではない型の意味を理解することが最善です。 1つは 'Sync'を実装するだけではありません。関連性の高い質問: https://stackoverflow.com/q/36649865/1233251 –

答えて

1

RustBoxは、スレッド間でそれを共有するなし(安全な)方法はありませんので(あなたがすでにSendを支持するだろう、まだマージされていないプルリクエストhttps://github.com/gchp/rustbox/pull/65を見つけたようだ)、Sendを実装していません。

プルリクエストは、あなたが、MutexにすなわちMutex<RustBox>RustBoxをラップする可能性がマージされます、そしてそれへの参照は、スレッド間で共有することができます。

しかし、あなたはrustbox参照がそれを使って新しいスレッドを生成するのに十分な長さではないので、生涯の問題になるでしょう。Arcにラップする必要があります。

let rustbox = Arc::new(Mutex::new(rustbox)); 

lock()それあなたがそれを使用するたびに:あなたはrustboxをラップする必要がありますあなたのmain機能で

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, " "); 
    }); 
} 

ロックを長すぎないようにしてください。それは例えば、これはより明確にするためにヘルパー変数を使用するのに役立つかもしれない:

let pe = rustbox.lock().unwrap().poll_event(false); 
match pe { 
// ... 
} 
+0

こんにちは、応答ありがとう!あなたが言ったように私は試してみましたが、実際に(現時点で)アンマーシャルされたPRで動作するようです。しかし、私はヘルパー変数 '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

関連する問題