From dbb97f0534b40a77e9d9883774aed209c9e49257 Mon Sep 17 00:00:00 2001 From: Robbert van der Helm Date: Sun, 23 Oct 2022 15:52:14 +0200 Subject: [PATCH] Use channels for Windows event loop Instead of an `ArrayQueue`. Since this doesn't need to both send and receive on the same object. --- src/event_loop/linux.rs | 18 ++++++++---------- src/event_loop/windows.rs | 14 ++++++-------- 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/src/event_loop/linux.rs b/src/event_loop/linux.rs index d5e0c713..d5288b3d 100644 --- a/src/event_loop/linux.rs +++ b/src/event_loop/linux.rs @@ -31,7 +31,7 @@ pub(crate) struct LinuxEventLoop { worker_thread: Option>, /// A channel for waking up the worker thread and having it perform one of the tasks from /// [`Message`]. - worker_thread_channel: channel::Sender>, + tasks_sender: channel::Sender>, } /// A message for communicating with the worker thread. @@ -48,7 +48,7 @@ where E: MainThreadExecutor + 'static, { fn new_and_spawn(executor: Arc) -> Self { - let (sender, receiver) = channel::bounded(super::TASK_QUEUE_CAPACITY); + let (tasks_sender, tasks_receiver) = channel::bounded(super::TASK_QUEUE_CAPACITY); Self { executor: executor.clone(), @@ -57,10 +57,10 @@ where worker_thread: Some( thread::Builder::new() .name(String::from("worker")) - .spawn(move || worker_thread(receiver, Arc::downgrade(&executor))) + .spawn(move || worker_thread(tasks_receiver, Arc::downgrade(&executor))) .expect("Could not spawn worker thread"), ), - worker_thread_channel: sender, + tasks_sender, } } @@ -69,9 +69,7 @@ where self.executor.execute(task, true); true } else { - self.worker_thread_channel - .try_send(Message::Task(task)) - .is_ok() + self.tasks_sender.try_send(Message::Task(task)).is_ok() } } @@ -84,7 +82,7 @@ where impl Drop for LinuxEventLoop { fn drop(&mut self) { - self.worker_thread_channel + self.tasks_sender .send(Message::Shutdown) .expect("Failed while sending worker thread shutdown request"); if let Some(join_handle) = self.worker_thread.take() { @@ -95,13 +93,13 @@ impl Drop for LinuxEventLoop { /// The worker thread used in [`EventLoop`] that executes incoming tasks on the event loop's /// executor. -fn worker_thread(receiver: channel::Receiver>, executor: Weak) +fn worker_thread(tasks_receiver: channel::Receiver>, executor: Weak) where T: Send, E: MainThreadExecutor, { loop { - match receiver.recv() { + match tasks_receiver.recv() { Ok(Message::Task(task)) => match executor.upgrade() { Some(e) => e.execute(task, true), None => { diff --git a/src/event_loop/windows.rs b/src/event_loop/windows.rs index 55a136ac..4f024813 100644 --- a/src/event_loop/windows.rs +++ b/src/event_loop/windows.rs @@ -1,7 +1,7 @@ //! An event loop for windows, using an invisible window to hook into the host's message loop. This //! has only been tested under Wine with [yabridge](https://github.com/robbert-vdh/yabridge). -use crossbeam::queue::ArrayQueue; +use crossbeam::channel; use std::ffi::{c_void, CString}; use std::mem; use std::ptr; @@ -51,7 +51,7 @@ pub(crate) struct WindowsEventLoop { /// A queue of tasks that still need to be performed. When something gets added to this queue /// we'll wake up the window, which then continues to pop tasks off this queue until it is /// empty. - tasks: Arc>, + tasks_sender: channel::Sender, } impl EventLoop for WindowsEventLoop @@ -60,8 +60,7 @@ where E: MainThreadExecutor + 'static, { fn new_and_spawn(executor: Arc) -> Self { - // We'll pass one copy of the this to the window, and we'll keep the other copy here - let tasks = Arc::new(ArrayQueue::new(super::TASK_QUEUE_CAPACITY)); + let (tasks_sender, tasks_receiver) = channel::bounded(super::TASK_QUEUE_CAPACITY); // Window classes need to have unique names or else multiple plugins loaded into the same // process will end up calling the other plugin's callbacks @@ -85,7 +84,6 @@ where // erased version of the polling loop. let callback: PollCallback = { let executor = Arc::downgrade(&executor); - let tasks = tasks.clone(); Box::new(move || { let executor = match executor.upgrade() { @@ -96,7 +94,7 @@ where } }; - while let Some(task) = tasks.pop() { + while let Ok(task) = tasks_receiver.try_recv() { executor.execute(task, true); } }) @@ -128,7 +126,7 @@ where main_thread_id: thread::current().id(), message_window: window, message_window_class_name: class_name, - tasks, + tasks_sender, } } @@ -137,7 +135,7 @@ where self.executor.execute(task, true); true } else { - let success = self.tasks.push(task).is_ok(); + let success = self.tasks_sender.try_send(task).is_ok(); if success { // Instead of polling on a timer, we can just wake up the window whenever there's a // new message.