Skip to content

Commit 7ef6372

Browse files
authored
example: Do not send Window to another thread (#287)
The threading implications of accessing a window from another thread are unclear, so Winit chooses to block on the main thread on macOS and iOS. This means that we have to send the surface width and height to the other thread instead of trying to access it dynamically from the window.
1 parent 9d33b01 commit 7ef6372

File tree

1 file changed

+27
-30
lines changed

1 file changed

+27
-30
lines changed

examples/winit_multithread.rs

Lines changed: 27 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -18,42 +18,35 @@ pub mod ex {
1818
type Surface = softbuffer::Surface<OwnedDisplayHandle, Arc<Window>>;
1919

2020
fn render_thread(
21-
window: Arc<Window>,
22-
do_render: mpsc::Receiver<Arc<Mutex<Surface>>>,
21+
do_render: mpsc::Receiver<(Arc<Mutex<Surface>>, NonZeroU32, NonZeroU32)>,
2322
done: mpsc::Sender<()>,
2423
) {
2524
loop {
2625
println!("waiting for render...");
27-
let Ok(surface) = do_render.recv() else {
26+
let Ok((surface, width, height)) = do_render.recv() else {
2827
println!("main thread destroyed");
2928
break;
3029
};
3130

3231
// Perform the rendering.
3332
let mut surface = surface.lock().unwrap();
34-
if let (Some(width), Some(height)) = {
35-
let size = window.inner_size();
36-
println!("got size: {size:?}");
37-
(NonZeroU32::new(size.width), NonZeroU32::new(size.height))
38-
} {
39-
println!("resizing...");
40-
surface.resize(width, height).unwrap();
41-
42-
let mut buffer = surface.buffer_mut().unwrap();
43-
for y in 0..buffer.height().get() {
44-
for x in 0..buffer.width().get() {
45-
let red = x % 255;
46-
let green = y % 255;
47-
let blue = (x * y) % 255;
48-
let index = y * buffer.width().get() + x;
49-
buffer[index as usize] = blue | (green << 8) | (red << 16);
50-
}
33+
println!("resizing...");
34+
surface.resize(width, height).unwrap();
35+
36+
let mut buffer = surface.buffer_mut().unwrap();
37+
for y in 0..buffer.height().get() {
38+
for x in 0..buffer.width().get() {
39+
let red = x % 255;
40+
let green = y % 255;
41+
let blue = (x * y) % 255;
42+
let index = y * buffer.width().get() + x;
43+
buffer[index as usize] = blue | (green << 8) | (red << 16);
5144
}
52-
53-
println!("presenting...");
54-
buffer.present().unwrap();
5545
}
5646

47+
println!("presenting...");
48+
buffer.present().unwrap();
49+
5750
// We're done, tell the main thread to keep going.
5851
done.send(()).ok();
5952
}
@@ -77,10 +70,7 @@ pub mod ex {
7770
let (start_render, do_render) = mpsc::channel();
7871
let (render_done, finish_render) = mpsc::channel();
7972
println!("starting thread...");
80-
std::thread::spawn({
81-
let window = window.clone();
82-
move || render_thread(window, do_render, render_done)
83-
});
73+
std::thread::spawn(move || render_thread(do_render, render_done));
8474

8575
(window, start_render, finish_render)
8676
},
@@ -105,9 +95,16 @@ pub mod ex {
10595
eprintln!("RedrawRequested fired before Resumed or after Suspended");
10696
return;
10797
};
108-
// Start the render and then finish it.
109-
start_render.send(surface.clone()).unwrap();
110-
finish_render.recv().unwrap();
98+
99+
let size = window.inner_size();
100+
println!("got size: {size:?}");
101+
if let (Some(width), Some(height)) =
102+
(NonZeroU32::new(size.width), NonZeroU32::new(size.height))
103+
{
104+
// Start the render and then finish it.
105+
start_render.send((surface.clone(), width, height)).unwrap();
106+
finish_render.recv().unwrap();
107+
}
111108
}
112109
WindowEvent::CloseRequested
113110
| WindowEvent::KeyboardInput {

0 commit comments

Comments
 (0)