Use weak references to the executor
So this cyclic reference can't keep it alive.
This commit is contained in:
parent
98076ff792
commit
565d9259c3
|
@ -16,7 +16,7 @@
|
|||
|
||||
//! Different contexts the plugin can use to make callbacks to the host in different...contexts.
|
||||
|
||||
use std::sync::Arc;
|
||||
use std::sync::Weak;
|
||||
|
||||
use crate::params::Param;
|
||||
|
||||
|
@ -66,7 +66,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.
|
||||
fn new_and_spawn(executor: Arc<E>) -> Self;
|
||||
fn new_and_spawn(executor: Weak<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
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
//! delegate expensive processing to another thread.
|
||||
|
||||
use crossbeam::channel;
|
||||
use std::sync::Arc;
|
||||
use std::sync::Weak;
|
||||
use std::thread::{self, JoinHandle, ThreadId};
|
||||
|
||||
use super::{EventLoop, MainThreadExecutor};
|
||||
|
@ -31,7 +31,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: Arc<E>,
|
||||
executor: Weak<E>,
|
||||
|
||||
/// The ID of the main thread. In practice this is the ID of the thread that created this task
|
||||
/// queue.
|
||||
|
@ -59,7 +59,7 @@ where
|
|||
T: Send,
|
||||
E: MainThreadExecutor<T>,
|
||||
{
|
||||
fn new_and_spawn(executor: Arc<E>) -> Self {
|
||||
fn new_and_spawn(executor: Weak<E>) -> Self {
|
||||
let (sender, receiver) = channel::bounded(super::TASK_QUEUE_CAPACITY);
|
||||
|
||||
Self {
|
||||
|
@ -83,8 +83,16 @@ where
|
|||
|
||||
fn do_maybe_async(&self, task: T) -> bool {
|
||||
if self.is_main_thread() {
|
||||
self.executor.execute(task);
|
||||
true
|
||||
match self.executor.upgrade() {
|
||||
Some(e) => {
|
||||
e.execute(task);
|
||||
true
|
||||
}
|
||||
None => {
|
||||
nih_log!("The executor doesn't exist but somehow it's still submitting tasks, this shouldn't be possible!");
|
||||
false
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.worker_thread_channel
|
||||
.try_send(Message::Task(task))
|
||||
|
@ -109,14 +117,20 @@ impl<T, E> Drop for LinuxEventLoop<T, E> {
|
|||
}
|
||||
|
||||
/// The worker thread used in [EventLoop] that executes incmoing tasks on the event loop's executor.
|
||||
fn worker_thread<T, E>(receiver: channel::Receiver<Message<T>>, executor: Arc<E>)
|
||||
fn worker_thread<T, E>(receiver: channel::Receiver<Message<T>>, executor: Weak<E>)
|
||||
where
|
||||
T: Send,
|
||||
E: MainThreadExecutor<T>,
|
||||
{
|
||||
loop {
|
||||
match receiver.recv() {
|
||||
Ok(Message::Task(task)) => executor.execute(task),
|
||||
Ok(Message::Task(task)) => match executor.upgrade() {
|
||||
Some(e) => e.execute(task),
|
||||
None => {
|
||||
nih_log!("Received a new task but the executor is no longer alive, shutting down worker");
|
||||
return;
|
||||
}
|
||||
},
|
||||
Ok(Message::Shutdown) => return,
|
||||
Err(err) => {
|
||||
nih_log!(
|
||||
|
|
|
@ -220,7 +220,7 @@ impl<P: Plugin> WrapperInner<'_, P> {
|
|||
// XXX: This unsafe block is unnecessary. rust-analyzer gets a bit confused and this this
|
||||
// `write()` function is from `IBStream` which it definitely is not.
|
||||
*unsafe { wrapper.event_loop.write() } =
|
||||
MaybeUninit::new(OsEventLoop::new_and_spawn(wrapper.clone()));
|
||||
MaybeUninit::new(OsEventLoop::new_and_spawn(Arc::downgrade(&wrapper)));
|
||||
|
||||
wrapper
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue