Clean up EventLoop API
By taking an `Arc<T>` instead of a `Weak<T>`. The `Weak` is only needed for the background threads.
This commit is contained in:
parent
21bfb57023
commit
967426453a
6 changed files with 16 additions and 43 deletions
|
@ -1,6 +1,6 @@
|
|||
//! An internal event loop for spooling tasks to the/a GUI thread.
|
||||
|
||||
use std::sync::Weak;
|
||||
use std::sync::Arc;
|
||||
|
||||
#[cfg(all(target_family = "unix", not(target_os = "macos")))]
|
||||
mod linux;
|
||||
|
@ -38,10 +38,7 @@ where
|
|||
{
|
||||
/// Create and start a new event loop. The thread this is called on will be designated as the
|
||||
/// main thread, so this should be called when constructing the wrapper.
|
||||
//
|
||||
// TODO: This use of `Weak` is a bit weird outside the context of the VST3 wrapper, but the
|
||||
// alternatives didn't feel right either.
|
||||
fn new_and_spawn(executor: Weak<E>) -> Self;
|
||||
fn new_and_spawn(executor: Arc<E>) -> Self;
|
||||
|
||||
/// Either post the function to the task queue so it can be delegated to the main thread, or
|
||||
/// execute the task directly if this is the main thread. This function needs to be callable at
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
//! delegate expensive processing to another thread.
|
||||
|
||||
use crossbeam::channel;
|
||||
use std::sync::Weak;
|
||||
use std::sync::{Arc, Weak};
|
||||
use std::thread::{self, JoinHandle, ThreadId};
|
||||
|
||||
use super::{EventLoop, MainThreadExecutor};
|
||||
|
@ -19,7 +19,7 @@ pub(crate) struct LinuxEventLoop<T, E> {
|
|||
/// The thing that ends up executing these tasks. The tasks are usually executed from the worker
|
||||
/// thread, but if the current thread is the main thread then the task cna also be executed
|
||||
/// directly.
|
||||
executor: Weak<E>,
|
||||
executor: Arc<E>,
|
||||
|
||||
/// The ID of the main thread. In practice this is the ID of the thread that created this task
|
||||
/// queue.
|
||||
|
@ -47,7 +47,7 @@ where
|
|||
T: Send + 'static,
|
||||
E: MainThreadExecutor<T> + 'static,
|
||||
{
|
||||
fn new_and_spawn(executor: Weak<E>) -> Self {
|
||||
fn new_and_spawn(executor: Arc<E>) -> Self {
|
||||
let (sender, receiver) = channel::bounded(super::TASK_QUEUE_CAPACITY);
|
||||
|
||||
Self {
|
||||
|
@ -57,7 +57,7 @@ where
|
|||
worker_thread: Some(
|
||||
thread::Builder::new()
|
||||
.name(String::from("worker"))
|
||||
.spawn(move || worker_thread(receiver, executor))
|
||||
.spawn(move || worker_thread(receiver, Arc::downgrade(&executor)))
|
||||
.expect("Could not spawn worker thread"),
|
||||
),
|
||||
worker_thread_channel: sender,
|
||||
|
@ -66,19 +66,8 @@ where
|
|||
|
||||
fn do_maybe_async(&self, task: T) -> bool {
|
||||
if self.is_main_thread() {
|
||||
match self.executor.upgrade() {
|
||||
Some(e) => {
|
||||
unsafe { e.execute(task) };
|
||||
true
|
||||
}
|
||||
None => {
|
||||
nih_trace!(
|
||||
"The executor doesn't exist but somehow it's still submitting tasks, this \
|
||||
shouldn't be possible!"
|
||||
);
|
||||
false
|
||||
}
|
||||
}
|
||||
unsafe { self.executor.execute(task) };
|
||||
true
|
||||
} else {
|
||||
self.worker_thread_channel
|
||||
.try_send(Message::Task(task))
|
||||
|
|
|
@ -6,7 +6,6 @@ use std::ffi::{c_void, CString};
|
|||
use std::mem;
|
||||
use std::ptr;
|
||||
use std::sync::Arc;
|
||||
use std::sync::Weak;
|
||||
use std::thread::{self, ThreadId};
|
||||
use windows::Win32::Foundation::{HINSTANCE, HWND, LPARAM, LRESULT, PSTR, WPARAM};
|
||||
use windows::Win32::System::{
|
||||
|
@ -38,7 +37,7 @@ pub(crate) struct WindowsEventLoop<T, E> {
|
|||
/// The thing that ends up executing these tasks. The tasks are usually executed from the worker
|
||||
/// thread, but if the current thread is the main thread then the task cna also be executed
|
||||
/// directly.
|
||||
executor: Weak<E>,
|
||||
executor: Arc<E>,
|
||||
|
||||
/// The ID of the main thread. In practice this is the ID of the thread that created this task
|
||||
/// queue.
|
||||
|
@ -60,7 +59,7 @@ where
|
|||
T: Send + 'static,
|
||||
E: MainThreadExecutor<T> + 'static,
|
||||
{
|
||||
fn new_and_spawn(executor: Weak<E>) -> Self {
|
||||
fn new_and_spawn(executor: Arc<E>) -> 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));
|
||||
|
||||
|
@ -85,7 +84,7 @@ where
|
|||
// can't pass the tasks queue and the executor to it directly, so this is a simple type
|
||||
// erased version of the polling loop.
|
||||
let callback: PollCallback = {
|
||||
let executor = executor.clone();
|
||||
let executor = Arc::downgrade(&executor);
|
||||
let tasks = tasks.clone();
|
||||
|
||||
Box::new(move || {
|
||||
|
@ -135,19 +134,8 @@ where
|
|||
|
||||
fn do_maybe_async(&self, task: T) -> bool {
|
||||
if self.is_main_thread() {
|
||||
match self.executor.upgrade() {
|
||||
Some(e) => {
|
||||
unsafe { e.execute(task) };
|
||||
true
|
||||
}
|
||||
None => {
|
||||
nih_trace!(
|
||||
"The executor doesn't exist but somehow it's still submitting tasks, this \
|
||||
shouldn't be possible!"
|
||||
);
|
||||
false
|
||||
}
|
||||
}
|
||||
unsafe { e.execute(task) };
|
||||
true
|
||||
} else {
|
||||
let success = self.tasks.push(task).is_ok();
|
||||
if success {
|
||||
|
|
|
@ -316,7 +316,7 @@ pub enum OutputParamEvent {
|
|||
/// Because CLAP has this [`clap_host::request_host_callback()`] function, we don't need to use
|
||||
/// `OsEventLoop` and can instead just request a main thread callback directly.
|
||||
impl<P: ClapPlugin> EventLoop<Task<P>, Wrapper<P>> for Wrapper<P> {
|
||||
fn new_and_spawn(_executor: std::sync::Weak<Self>) -> Self {
|
||||
fn new_and_spawn(_executor: std::sync::Arc<Self>) -> Self {
|
||||
panic!("What are you doing");
|
||||
}
|
||||
|
||||
|
|
|
@ -214,7 +214,7 @@ impl<P: Plugin, B: Backend> Wrapper<P, B> {
|
|||
// Initialized later as it needs a reference to the wrapper for the async executor
|
||||
editor: AtomicRefCell::new(None),
|
||||
|
||||
event_loop: OsEventLoop::new_and_spawn(Arc::downgrade(&task_executor_wrapper)),
|
||||
event_loop: OsEventLoop::new_and_spawn(task_executor_wrapper),
|
||||
|
||||
bus_config: BusConfig {
|
||||
num_input_channels: config.input_channels.unwrap_or(P::DEFAULT_INPUT_CHANNELS),
|
||||
|
|
|
@ -329,8 +329,7 @@ impl<P: Vst3Plugin> WrapperInner<P> {
|
|||
// serving multiple plugin instances, Arc can't be used because its reference count
|
||||
// is separate from the internal COM-style reference count.
|
||||
let wrapper: Arc<WrapperInner<P>> = wrapper.into();
|
||||
*wrapper.event_loop.borrow_mut() =
|
||||
Some(OsEventLoop::new_and_spawn(Arc::downgrade(&wrapper)));
|
||||
*wrapper.event_loop.borrow_mut() = Some(OsEventLoop::new_and_spawn(wrapper.clone()));
|
||||
|
||||
// The editor also needs to be initialized later so the Async executor can work.
|
||||
*wrapper.editor.borrow_mut() = wrapper
|
||||
|
|
Loading…
Add table
Reference in a new issue