Задача сделать так, чтобы все события клавиатуры обрабатывались в своём цикле в отдельном треде. Сделать без треда у меня получилось, когда добавляю тред начинается какой то ад с владением над переменными и полная консоль ошибок.
Вот код:
Cargo.toml
[package]
name = "test"
version = "0.0.1-alpha.0"
edition = "2018"
[dependencies]
sdl3 = { version = "0.14.26", features = ["build-from-source"]}
gl = "0.14.0"
[dev-dependencies]
main.rs
use std::sync::{Arc, Mutex};
use std::thread;
fn main() {
let mut win = test::win::init("Test", 1920, 1080);
gl::load_with(|s| win.video_subsystem.gl_get_proc_address(s).unwrap() as *const _);
let offset_x = Arc::new(Mutex::new(0));
let a_clone_offset_x = Arc::clone(&offset_x);
win.key_handlers.insert("A".to_string(), Box::new(move || {
*a_clone_offset_x.lock().unwrap() -= 1;
println!("{:?}", a_clone_offset_x);
}));
let d_clone_offset_x = Arc::clone(&offset_x);
win.key_handlers.insert("D".to_string(), Box::new(move || {
*d_clone_offset_x.lock().unwrap() += 1;
println!("{:?}", d_clone_offset_x);
}));
// thread::spawn(move || {
win.handle_events();
// });
loop {};
}
win.rs
use sdl3::{Sdl, VideoSubsystem, EventPump};
use sdl3::video::{GLProfile, GLContext, Window};
use std::collections::HashMap;
pub struct Win {
pub sdl_context: Sdl,
pub video_subsystem: VideoSubsystem,
pub window: Window,
pub gl_context: GLContext,
pub event_pump: EventPump,
pub key_handlers: HashMap<String, Box<dyn Fn() -> () >>,
}
pub fn init(title: &str, width: u32, height: u32) -> Win {
let sdl_context = sdl3::init().unwrap();
let video_subsystem = sdl_context.video().unwrap();
let gl_attr = video_subsystem.gl_attr();
gl_attr.set_context_profile(GLProfile::Core);
gl_attr.set_context_flags().debug().set();
gl_attr.set_context_version(3, 3);
gl_attr.set_multisample_buffers(1);
gl_attr.set_multisample_samples(4);
let window = video_subsystem.window(title, width, height)
.position_centered()
.resizable()
// .maximized()
// .fullscreen()
.opengl()
.build()
.unwrap();
let gl_context = window.gl_create_context().unwrap();
let event_pump = sdl_context.event_pump().unwrap();
let key_handlers = HashMap::new();
Win {sdl_context, video_subsystem, window, gl_context, event_pump, key_handlers}
}
impl Win {
pub fn handle_events(&mut self) {
let event_pump = &mut self.event_pump;
loop {
use sdl3::event::Event;
use sdl3::event::Event::KeyDown;
use sdl3::keyboard::Keycode::*;
let event = event_pump.wait_event();
// println!("{:?}", event);
match event {
Event::Quit {..} => std::process::exit(123),
KeyDown { keycode: Some(A), .. } => self.key_handlers["A"](),
KeyDown { keycode: Some(D), .. } => self.key_handlers["D"](),
_ => {}
}
}
}
}
Если в main.rs добавить тред вокруг win.handle_events();
получаю вот это
error[E0277]: `*mut sdl3_sys::generated::video::SDL_GLContextState` cannot be sent between threads safely
--> src/main.rs:23:17
|
23 | thread::spawn(move || {
| ------------- ^------
| | |
| ___|_____________within this `{closure@src/main.rs:23:17: 23:24}`
| | |
| | required by a bound introduced by this call
24 | | win.handle_events();
25 | | });
| |___^ `*mut sdl3_sys::generated::video::SDL_GLContextState` cannot be sent between threads safely
|
= help: within `{closure@src/main.rs:23:17: 23:24}`, the trait `Send` is not implemented for `*mut sdl3_sys::generated::video::SDL_GLContextState`
note: required because it appears within the type `sdl3::video::GLContext`
--> /home/archer/.asdf/installs/rust/1.84.1/registry/src/index.crates.io-6f17d22bba15001f/sdl3-0.14.26/src/sdl3/video.rs:519:12
|
519 | pub struct GLContext {
| ^^^^^^^^^
note: required because it appears within the type `Win`
--> /home/archer/Work/Test/src/win.rs:5:12
|
5 | pub struct Win {
| ^^^
note: required because it's used within this closure
--> src/main.rs:23:17
|
23 | thread::spawn(move || {
| ^^^^^^^
note: required by a bound in `spawn`
--> /rustc/e71f9a9a98b0faf423844bf0ba7438f29dc27d58/library/std/src/thread/mod.rs:724:1
error[E0277]: `*mut ()` cannot be sent between threads safely
--> src/main.rs:23:17
|
23 | thread::spawn(move || {
| ------------- ^------
| | |
| ___|_____________within this `{closure@src/main.rs:23:17: 23:24}`
| | |
| | required by a bound introduced by this call
24 | | win.handle_events();
25 | | });
| |___^ `*mut ()` cannot be sent between threads safely
|
= help: within `{closure@src/main.rs:23:17: 23:24}`, the trait `Send` is not implemented for `*mut ()`
note: required because it appears within the type `PhantomData<*mut ()>`
--> /rustc/e71f9a9a98b0faf423844bf0ba7438f29dc27d58/library/core/src/marker.rs:753:12
note: required because it appears within the type `sdl3::sdl::VideoSubsystem`
--> /home/archer/.asdf/installs/rust/1.84.1/registry/src/index.crates.io-6f17d22bba15001f/sdl3-0.14.26/src/sdl3/sdl.rs:308:12
|
308 | subsystem!(VideoSubsystem, SDL_INIT_VIDEO, VIDEO_COUNT, nosync);
| ^^^^^^^^^^^^^^
note: required because it appears within the type `Win`
--> /home/archer/Work/Test/src/win.rs:5:12
|
5 | pub struct Win {
| ^^^
note: required because it's used within this closure
--> src/main.rs:23:17
|
23 | thread::spawn(move || {
| ^^^^^^^
note: required by a bound in `spawn`
--> /rustc/e71f9a9a98b0faf423844bf0ba7438f29dc27d58/library/std/src/thread/mod.rs:724:1
error[E0277]: `*mut sdl3_sys::generated::video::SDL_Window` cannot be shared between threads safely
--> src/main.rs:23:17
|
23 | thread::spawn(move || {
| ___-------------_^
| | |
| | required by a bound introduced by this call
24 | | win.handle_events();
25 | | });
| |___^ `*mut sdl3_sys::generated::video::SDL_Window` cannot be shared between threads safely
|
= help: within `sdl3::video::WindowContext`, the trait `Sync` is not implemented for `*mut sdl3_sys::generated::video::SDL_Window`
note: required because it appears within the type `sdl3::video::WindowContext`
--> /home/archer/.asdf/installs/rust/1.84.1/registry/src/index.crates.io-6f17d22bba15001f/sdl3-0.14.26/src/sdl3/video.rs:544:12
|
544 | pub struct WindowContext {
| ^^^^^^^^^^^^^
= note: required for `Arc<sdl3::video::WindowContext>` to implement `Send`
note: required because it appears within the type `sdl3::video::Window`
--> /home/archer/.asdf/installs/rust/1.84.1/registry/src/index.crates.io-6f17d22bba15001f/sdl3-0.14.26/src/sdl3/video.rs:683:12
|
683 | pub struct Window {
| ^^^^^^
note: required because it appears within the type `Win`
--> /home/archer/Work/Test/src/win.rs:5:12
|
5 | pub struct Win {
| ^^^
note: required because it's used within this closure
--> src/main.rs:23:17
|
23 | thread::spawn(move || {
| ^^^^^^^
note: required by a bound in `spawn`
--> /rustc/e71f9a9a98b0faf423844bf0ba7438f29dc27d58/library/std/src/thread/mod.rs:724:1
error[E0277]: `*mut c_void` cannot be shared between threads safely
--> src/main.rs:23:17
|
23 | thread::spawn(move || {
| ___-------------_^
| | |
| | required by a bound introduced by this call
24 | | win.handle_events();
25 | | });
| |___^ `*mut c_void` cannot be shared between threads safely
|
= help: within `sdl3::video::WindowContext`, the trait `Sync` is not implemented for `*mut c_void`
note: required because it appears within the type `sdl3::video::WindowContext`
--> /home/archer/.asdf/installs/rust/1.84.1/registry/src/index.crates.io-6f17d22bba15001f/sdl3-0.14.26/src/sdl3/video.rs:544:12
|
544 | pub struct WindowContext {
| ^^^^^^^^^^^^^
= note: required for `Arc<sdl3::video::WindowContext>` to implement `Send`
note: required because it appears within the type `sdl3::video::Window`
--> /home/archer/.asdf/installs/rust/1.84.1/registry/src/index.crates.io-6f17d22bba15001f/sdl3-0.14.26/src/sdl3/video.rs:683:12
|
683 | pub struct Window {
| ^^^^^^
note: required because it appears within the type `Win`
--> /home/archer/Work/Test/src/win.rs:5:12
|
5 | pub struct Win {
| ^^^
note: required because it's used within this closure
--> src/main.rs:23:17
|
23 | thread::spawn(move || {
| ^^^^^^^
note: required by a bound in `spawn`
--> /rustc/e71f9a9a98b0faf423844bf0ba7438f29dc27d58/library/std/src/thread/mod.rs:724:1
error[E0277]: `*mut sdl3_sys::generated::video::SDL_Window` cannot be sent between threads safely
--> src/main.rs:23:17
|
23 | thread::spawn(move || {
| ___-------------_^
| | |
| | required by a bound introduced by this call
24 | | win.handle_events();
25 | | });
| |___^ `*mut sdl3_sys::generated::video::SDL_Window` cannot be sent between threads safely
|
= help: within `sdl3::video::WindowContext`, the trait `Send` is not implemented for `*mut sdl3_sys::generated::video::SDL_Window`
note: required because it appears within the type `sdl3::video::WindowContext`
--> /home/archer/.asdf/installs/rust/1.84.1/registry/src/index.crates.io-6f17d22bba15001f/sdl3-0.14.26/src/sdl3/video.rs:544:12
|
544 | pub struct WindowContext {
| ^^^^^^^^^^^^^
= note: required for `Arc<sdl3::video::WindowContext>` to implement `Send`
note: required because it appears within the type `sdl3::video::Window`
--> /home/archer/.asdf/installs/rust/1.84.1/registry/src/index.crates.io-6f17d22bba15001f/sdl3-0.14.26/src/sdl3/video.rs:683:12
|
683 | pub struct Window {
| ^^^^^^
note: required because it appears within the type `Win`
--> /home/archer/Work/Test/src/win.rs:5:12
|
5 | pub struct Win {
| ^^^
note: required because it's used within this closure
--> src/main.rs:23:17
|
23 | thread::spawn(move || {
| ^^^^^^^
note: required by a bound in `spawn`
--> /rustc/e71f9a9a98b0faf423844bf0ba7438f29dc27d58/library/std/src/thread/mod.rs:724:1
error[E0277]: `*mut c_void` cannot be sent between threads safely
--> src/main.rs:23:17
|
23 | thread::spawn(move || {
| ___-------------_^
| | |
| | required by a bound introduced by this call
24 | | win.handle_events();
25 | | });
| |___^ `*mut c_void` cannot be sent between threads safely
|
= help: within `sdl3::video::WindowContext`, the trait `Send` is not implemented for `*mut c_void`
note: required because it appears within the type `sdl3::video::WindowContext`
--> /home/archer/.asdf/installs/rust/1.84.1/registry/src/index.crates.io-6f17d22bba15001f/sdl3-0.14.26/src/sdl3/video.rs:544:12
|
544 | pub struct WindowContext {
| ^^^^^^^^^^^^^
= note: required for `Arc<sdl3::video::WindowContext>` to implement `Send`
note: required because it appears within the type `sdl3::video::Window`
--> /home/archer/.asdf/installs/rust/1.84.1/registry/src/index.crates.io-6f17d22bba15001f/sdl3-0.14.26/src/sdl3/video.rs:683:12
|
683 | pub struct Window {
| ^^^^^^
note: required because it appears within the type `Win`
--> /home/archer/Work/Test/src/win.rs:5:12
|
5 | pub struct Win {
| ^^^
note: required because it's used within this closure
--> src/main.rs:23:17
|
23 | thread::spawn(move || {
| ^^^^^^^
note: required by a bound in `spawn`
--> /rustc/e71f9a9a98b0faf423844bf0ba7438f29dc27d58/library/std/src/thread/mod.rs:724:1
error[E0277]: `*mut ()` cannot be shared between threads safely
--> src/main.rs:23:17
|
23 | thread::spawn(move || {
| ___-------------_^
| | |
| | required by a bound introduced by this call
24 | | win.handle_events();
25 | | });
| |___^ `*mut ()` cannot be shared between threads safely
|
= help: within `sdl3::video::WindowContext`, the trait `Sync` is not implemented for `*mut ()`
note: required because it appears within the type `PhantomData<*mut ()>`
--> /rustc/e71f9a9a98b0faf423844bf0ba7438f29dc27d58/library/core/src/marker.rs:753:12
note: required because it appears within the type `sdl3::sdl::VideoSubsystem`
--> /home/archer/.asdf/installs/rust/1.84.1/registry/src/index.crates.io-6f17d22bba15001f/sdl3-0.14.26/src/sdl3/sdl.rs:308:12
|
308 | subsystem!(VideoSubsystem, SDL_INIT_VIDEO, VIDEO_COUNT, nosync);
| ^^^^^^^^^^^^^^
note: required because it appears within the type `sdl3::video::WindowContext`
--> /home/archer/.asdf/installs/rust/1.84.1/registry/src/index.crates.io-6f17d22bba15001f/sdl3-0.14.26/src/sdl3/video.rs:544:12
|
544 | pub struct WindowContext {
| ^^^^^^^^^^^^^
= note: required for `Arc<sdl3::video::WindowContext>` to implement `Send`
note: required because it appears within the type `sdl3::video::Window`
--> /home/archer/.asdf/installs/rust/1.84.1/registry/src/index.crates.io-6f17d22bba15001f/sdl3-0.14.26/src/sdl3/video.rs:683:12
|
683 | pub struct Window {
| ^^^^^^
note: required because it appears within the type `Win`
--> /home/archer/Work/Test/src/win.rs:5:12
|
5 | pub struct Win {
| ^^^
note: required because it's used within this closure
--> src/main.rs:23:17
|
23 | thread::spawn(move || {
| ^^^^^^^
note: required by a bound in `spawn`
--> /rustc/e71f9a9a98b0faf423844bf0ba7438f29dc27d58/library/std/src/thread/mod.rs:724:1
error[E0277]: `(dyn Fn() + 'static)` cannot be sent between threads safely
--> src/main.rs:23:17
|
23 | thread::spawn(move || {
| ___-------------_^
| | |
| | required by a bound introduced by this call
24 | | win.handle_events();
25 | | });
| |___^ `(dyn Fn() + 'static)` cannot be sent between threads safely
|
= help: the trait `Send` is not implemented for `(dyn Fn() + 'static)`
= note: required for `Unique<(dyn Fn() + 'static)>` to implement `Send`
note: required because it appears within the type `Box<(dyn Fn() + 'static)>`
--> /rustc/e71f9a9a98b0faf423844bf0ba7438f29dc27d58/library/alloc/src/boxed.rs:233:12
= note: required because it appears within the type `(String, Box<(dyn Fn() + 'static)>)`
= note: required for `hashbrown::raw::RawTable<(String, Box<(dyn Fn() + 'static)>)>` to implement `Send`
note: required because it appears within the type `hashbrown::map::HashMap<String, Box<(dyn Fn() + 'static)>, RandomState>`
--> /rust/deps/hashbrown-0.15.0/src/map.rs:185:12
note: required because it appears within the type `HashMap<String, Box<(dyn Fn() + 'static)>>`
--> /rustc/e71f9a9a98b0faf423844bf0ba7438f29dc27d58/library/std/src/collections/hash/map.rs:211:12
note: required because it appears within the type `Win`
--> /home/archer/Work/Test/src/win.rs:5:12
|
5 | pub struct Win {
| ^^^
note: required because it's used within this closure
--> src/main.rs:23:17
|
23 | thread::spawn(move || {
| ^^^^^^^
note: required by a bound in `spawn`
--> /rustc/e71f9a9a98b0faf423844bf0ba7438f29dc27d58/library/std/src/thread/mod.rs:724:1
help: use parentheses to call this trait object
|
25 | }());
| ++
For more information about this error, try `rustc --explain E0277`.
error: could not compile `test` (bin "test") due to 8 previous errors
Подскажите как сделать правильно?