summaryrefslogtreecommitdiff
path: root/engine/src/windowing.rs
diff options
context:
space:
mode:
authorHampusM <hampus@hampusmat.com>2026-05-31 23:43:23 +0200
committerHampusM <hampus@hampusmat.com>2026-05-31 23:43:23 +0200
commit81eb01170da4334dce88bd0d9e815d6d28e3c796 (patch)
treea29610db60b7548a7a2aadd8e7ef14084a0a0ffb /engine/src/windowing.rs
parentac9bbe183e144105b117f78d923ed5b258c12f69 (diff)
refactor(engine): replace windowing app message channels with queues
Diffstat (limited to 'engine/src/windowing.rs')
-rw-r--r--engine/src/windowing.rs131
1 files changed, 59 insertions, 72 deletions
diff --git a/engine/src/windowing.rs b/engine/src/windowing.rs
index 096a23f..fac1c62 100644
--- a/engine/src/windowing.rs
+++ b/engine/src/windowing.rs
@@ -1,14 +1,9 @@
use std::hint::cold_path;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, Weak};
-use std::thread::{Builder as ThreadBuilder, JoinHandle as ThreadJoinHandle};
+use std::thread::Builder as ThreadBuilder;
-use crossbeam_channel::{
- bounded as bounded_channel,
- Receiver as ChannelReceiver,
- Sender as ChannelSender,
- TrySendError,
-};
+use crossbeam_queue::ArrayQueue;
use raw_window_handle::{DisplayHandle, HandleError, HasDisplayHandle, WindowHandle};
use winit::application::ApplicationHandler;
use winit::dpi::PhysicalPosition;
@@ -55,9 +50,9 @@ pub mod keyboard;
pub mod mouse;
pub mod window;
-const MESSAGE_FROM_APP_CHANNEL_CAP: usize = 512;
+const MESSAGE_FROM_APP_QUEUE_SIZE: usize = 512;
-const MESSAGE_TO_APP_CHANNEL_CAP: usize = 16; // Increase if more messages are added
+const MESSAGE_TO_APP_QUEUE_SIZE: usize = 16; // Increase if more messages are added
declare_entity!(
pub PHASE,
@@ -144,13 +139,13 @@ fn update_stuff(
.into();
let Context {
- ref message_from_app_receiver,
+ ref message_from_app_queue,
ref mut display_handle,
ref mut windows,
..
} = *context;
- for message in message_from_app_receiver.try_iter() {
+ for message in iter_array_queue(message_from_app_queue) {
tracing::trace!(message=?message, "Received message from app");
match message {
@@ -304,9 +299,8 @@ fn handle_window_removed(
#[derive(Debug, Sole)]
pub struct Context
{
- _thread: ThreadJoinHandle<()>,
- message_from_app_receiver: ChannelReceiver<MessageFromApp>,
- message_to_app_sender: ChannelSender<MessageToApp>,
+ message_from_app_queue: Arc<ArrayQueue<MessageFromApp>>,
+ message_to_app_queue: Arc<ArrayQueue<MessageToApp>>,
shared_state: Arc<SharedState>,
display_handle: Option<OwnedDisplayHandle>,
windows: MapVec<WindowId, (Arc<winit::window::Window>, Uid)>,
@@ -350,15 +344,10 @@ impl Context
fn try_send_message_to_app(&self, message: MessageToApp)
{
- if let Err(err) = self.message_to_app_sender.try_send(message) {
- let error = match &err {
- TrySendError::Full(_) => TrySendError::Full(()),
- TrySendError::Disconnected(_) => TrySendError::Disconnected(()),
- };
-
- let message = err.into_inner();
-
- tracing::error!("Failed to send message {error}: {message:?}");
+ if self.message_to_app_queue.push(message).is_err() {
+ tracing::error!(
+ "Failed to send message. Queue for messages to windowing app is full"
+ );
}
}
}
@@ -367,46 +356,49 @@ impl Default for Context
{
fn default() -> Self
{
- let (message_from_app_sender, message_from_app_receiver) =
- bounded_channel::<MessageFromApp>(MESSAGE_FROM_APP_CHANNEL_CAP);
+ let message_from_app_queue = Arc::new(ArrayQueue::<MessageFromApp>::new(
+ MESSAGE_FROM_APP_QUEUE_SIZE,
+ ));
- let message_from_app_receiver_b = message_from_app_receiver.clone();
+ let message_from_app_queue_b = message_from_app_queue.clone();
- let (message_to_app_sender, message_to_app_receiver) =
- bounded_channel::<MessageToApp>(MESSAGE_TO_APP_CHANNEL_CAP);
+ let message_to_app_queue =
+ Arc::new(ArrayQueue::<MessageToApp>::new(MESSAGE_TO_APP_QUEUE_SIZE));
+
+ let message_to_app_queue_b = message_to_app_queue.clone();
let shared_state = Arc::new(SharedState::default());
let shared_state_b = shared_state.clone();
- Self {
- _thread: ThreadBuilder::new()
- .name("windowing".to_string())
- .spawn(move || {
- let mut app = App {
- message_from_app_sender,
- message_from_app_receiver: message_from_app_receiver_b,
- message_to_app_receiver,
- shared_state: shared_state_b,
- windows: MapVec::default(),
- };
+ ThreadBuilder::new()
+ .name("windowing app".to_string())
+ .spawn(move || {
+ let mut app = App {
+ message_from_app_queue: message_from_app_queue_b,
+ message_to_app_queue: message_to_app_queue_b,
+ shared_state: shared_state_b,
+ windows: MapVec::default(),
+ };
- let event_loop = match create_event_loop() {
- Ok(event_loop) => event_loop,
- Err(err) => {
- tracing::error!("Failed to create event loop: {err}");
- return;
- }
- };
+ let event_loop = match create_event_loop() {
+ Ok(event_loop) => event_loop,
+ Err(err) => {
+ tracing::error!("Failed to create event loop: {err}");
+ return;
+ }
+ };
- event_loop.set_control_flow(EventLoopControlFlow::Poll);
+ event_loop.set_control_flow(EventLoopControlFlow::Poll);
- if let Err(err) = event_loop.run_app(&mut app) {
- tracing::error!("Event loop error occurred: {err}");
- }
- })
- .expect("Failed to create windowing thread"),
- message_from_app_receiver,
- message_to_app_sender,
+ if let Err(err) = event_loop.run_app(&mut app) {
+ tracing::error!("Event loop error occurred: {err}");
+ }
+ })
+ .expect("Failed to create windowing thread");
+
+ Self {
+ message_from_app_queue,
+ message_to_app_queue,
shared_state,
display_handle: None,
windows: MapVec::default(),
@@ -486,9 +478,8 @@ impl Default for SharedState
#[derive(Debug)]
struct App
{
- message_from_app_sender: ChannelSender<MessageFromApp>,
- message_from_app_receiver: ChannelReceiver<MessageFromApp>,
- message_to_app_receiver: ChannelReceiver<MessageToApp>,
+ message_from_app_queue: Arc<ArrayQueue<MessageFromApp>>,
+ message_to_app_queue: Arc<ArrayQueue<MessageToApp>>,
shared_state: Arc<SharedState>,
windows: MapVec<WindowId, (Weak<WinitWindow>, WindowSettings)>,
}
@@ -498,7 +489,7 @@ impl App
#[tracing::instrument(skip_all)]
fn handle_received_messages(&mut self, event_loop: &ActiveEventLoop)
{
- for message in self.message_to_app_receiver.try_iter() {
+ for message in iter_array_queue(&self.message_to_app_queue) {
match message {
MessageToApp::CreateWindow(window_ent_id, window_creation_attrs) => {
tracing::info!(
@@ -549,24 +540,13 @@ impl App
#[tracing::instrument(skip_all)]
fn send_message(&self, message: MessageFromApp)
{
- if self.message_from_app_sender.is_full() {
+ if self.message_from_app_queue.is_full() {
tracing::warn!(
- "Message channel is full! Dropping oldest message from channel"
+ "Queue for messages to windowing app is full! Dropping oldest message"
);
-
- self.message_from_app_receiver.try_recv().ok();
}
- if let Err(err) = self.message_from_app_sender.try_send(message) {
- let error = match &err {
- TrySendError::Full(_) => TrySendError::Full(()),
- TrySendError::Disconnected(_) => TrySendError::Disconnected(()),
- };
-
- let message = err.into_inner();
-
- tracing::error!("Failed to send message {error}: {message:?}");
- }
+ self.message_from_app_queue.force_push(message);
}
}
@@ -749,3 +729,10 @@ struct WindowSettings
{
cursor_grab_mode: CursorGrabMode,
}
+
+fn iter_array_queue<Item>(
+ queue: &ArrayQueue<Item>,
+) -> impl Iterator<Item = Item> + use<'_, Item>
+{
+ (0..queue.len()).into_iter().filter_map(|_| queue.pop())
+}