2017-08-27 5 views
1

描画コールを実行するためにsdl2-rsクレートでタイマーを開始したいとします。私はこのような何かやってそれを起動したい:SDL2、FnMutとmpsc、送信者をスレッド間で安全に共有することはできません

extern crate sdl2; 

use std::sync::mpsc; 

enum Event { 
    Draw, 
} 

fn main() { 
    let sdl_context = sdl2::init().unwrap(); 
    let video_subsystem = sdl_context.video().unwrap(); 
    video_subsystem.gl_attr().set_context_version(4, 5); 
    println!(
     "Current gl version: {:?}", 
     video_subsystem.gl_attr().context_version() 
    ); 
    let timer_subsystem = sdl_context.timer().unwrap(); 

    let window = video_subsystem 
     .window("rust-sdl2 demo: Video", 800, 600) 
     .position_centered() 
     .opengl() 
     .build() 
     .unwrap(); 

    let context = window.gl_create_context().unwrap(); 

    let (tx, rx) = mpsc::channel(); 
    { 
     let timer_tx = tx.clone(); 
     timer_subsystem.add_timer(
      1000u32/120u32, 
      Box::new(move || { 
       timer_tx.send(Event::Draw); 
       1000u32/120u32 
      }), 
     ); 
    } 
} 

をしかし、私はこのエラーを取得:

error[E0277]: the trait bound `std::sync::mpsc::Sender<Event>: std::marker::Sync` is not satisfied in `[[email protected]/main.rs:33:22: 36:14 timer_tx:std::sync::mpsc::Sender<Event>]` 
    --> src/main.rs:33:13 
    | 
33 |/   Box::new(move || { 
34 | |     timer_tx.send(Event::Draw); 
35 | |     1000u32/120u32 
36 | |    }), 
    | |______________^ `std::sync::mpsc::Sender<Event>` cannot be shared between threads safely 
    | 
    = help: within `[[email protected]/main.rs:33:22: 36:14 timer_tx:std::sync::mpsc::Sender<Event>]`, the trait `std::marker::Sync` is not implemented for `std::sync::mpsc::Sender<Event>` 
    = note: required because it appears within the type `[[email protected]/main.rs:33:22: 36:14 timer_tx:std::sync::mpsc::Sender<Event>]` 
    = note: required for the cast to the object type `std::ops::FnMut() -> u32 + std::marker::Sync` 

私は、送信者がSyncではないことを理解ので、私はそれのクローンを作成し、中にクローン化したオブジェクトを移動しますFnMut終了ですが、とにかく動作しません。どうやってやるの?オブジェクトをクロージャーに移動することによって私が理解したところから、を共有しないので、このように動作する必要があります。また、ドキュメントの例も同じです。

答えて

0

複製された送信者は元の送信者と同じ種類ですので、まだSyncではありません。 add_timer関数はSyncのクロージャを必要とするので、送信者をスレッド間で共有することを安全にするMutexに送信者をラップする必要があります。

let timer_tx = Mutex::new(tx.clone()); 
timer_subsystem.add_timer(
    1000u32/120u32, 
    Box::new(move || { 
     timer_tx.lock().unwrap().send(Event::Draw); 
     1000u32/120u32 
    }), 
); 
+0

これは間違いありませんが、クローン作成の場合は同期する必要はありません。別のオブジェクトを使用しています。共有するものは何もないと思います。または私はここで間違っていますか? –

+0

'add_timer'は' Sync'を必要とします。あなたは要件に従わなければなりません。 – red75prime

関連する問題