diff options
| author | HampusM <hampus@hampusmat.com> | 2026-05-31 23:43:23 +0200 |
|---|---|---|
| committer | HampusM <hampus@hampusmat.com> | 2026-05-31 23:43:23 +0200 |
| commit | 81eb01170da4334dce88bd0d9e815d6d28e3c796 (patch) | |
| tree | a29610db60b7548a7a2aadd8e7ef14084a0a0ffb | |
| parent | ac9bbe183e144105b117f78d923ed5b258c12f69 (diff) | |
refactor(engine): replace windowing app message channels with queues
| -rw-r--r-- | Cargo.lock | 8 | ||||
| -rw-r--r-- | engine/Cargo.toml | 2 | ||||
| -rw-r--r-- | engine/src/windowing.rs | 131 |
3 files changed, 64 insertions, 77 deletions
@@ -489,10 +489,10 @@ dependencies = [ ] [[package]] -name = "crossbeam-channel" -version = "0.5.15" +name = "crossbeam-queue" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" +checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" dependencies = [ "crossbeam-utils", ] @@ -565,7 +565,7 @@ dependencies = [ "bitflags 2.11.1", "build-rs", "cfg_aliases", - "crossbeam-channel", + "crossbeam-queue", "engine-ecs", "engine-macros", "glutin", diff --git a/engine/Cargo.toml b/engine/Cargo.toml index 260bb56..1e10d42 100644 --- a/engine/Cargo.toml +++ b/engine/Cargo.toml @@ -12,9 +12,9 @@ tracing = "0.1.39" seq-macro = "0.3.5" paste = "1.0.14" parking_lot = "0.12.3" -crossbeam-channel = "0.5.15" safer-ffi = "0.1.13" nu-ansi-term = "0.46.0" +crossbeam-queue = "0.3.12" engine-ecs = { workspace = true } util-macros = { workspace = true } opengl-bindings = { workspace = true } 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()) +} |
