1
0
Fork 0

Remove Sync bound from TaskExecutor

This commit is contained in:
Robbert van der Helm 2022-10-22 12:31:54 +02:00
parent f6ad85de01
commit 5a974219b8
7 changed files with 16 additions and 13 deletions

View file

@ -10,7 +10,10 @@ use crate::params::Params;
use crate::wrapper::clap::features::ClapFeature; use crate::wrapper::clap::features::ClapFeature;
use crate::wrapper::state::PluginState; use crate::wrapper::state::PluginState;
pub type TaskExecutor<P> = Box<dyn Fn(<P as Plugin>::BackgroundTask) + Send + Sync>; /// A function that can execute a plugin's [`BackgroundTask`][Plugin::BackgroundTask]s. A plugin can
/// dispatch these tasks from the `initialize()` function, the `process()` function, or the GUI, so
/// they can be deferred for later to avoid blocking realtime contexts.
pub type TaskExecutor<P> = Box<dyn Fn(<P as Plugin>::BackgroundTask) + Send>;
/// Basic functionality that needs to be implemented by a plugin. The wrappers will use this to /// Basic functionality that needs to be implemented by a plugin. The wrappers will use this to
/// expose the plugin in a particular plugin format. /// expose the plugin in a particular plugin format.

View file

@ -115,7 +115,7 @@ impl<P: ClapPlugin> GuiContext for WrapperGuiContext<P> {
impl<P: ClapPlugin> InitContext<P> for WrapperInitContext<'_, P> { impl<P: ClapPlugin> InitContext<P> for WrapperInitContext<'_, P> {
fn execute(&self, task: P::BackgroundTask) { fn execute(&self, task: P::BackgroundTask) {
(self.wrapper.task_executor)(task); (self.wrapper.task_executor.lock())(task);
} }
fn plugin_api(&self) -> PluginApi { fn plugin_api(&self) -> PluginApi {

View file

@ -107,7 +107,7 @@ pub struct Wrapper<P: ClapPlugin> {
/// The wrapped plugin instance. /// The wrapped plugin instance.
plugin: Mutex<P>, plugin: Mutex<P>,
/// The plugin's background task executor closure. /// The plugin's background task executor closure.
pub task_executor: TaskExecutor<P>, pub task_executor: Mutex<TaskExecutor<P>>,
/// The plugin's parameters. These are fetched once during initialization. That way the /// The plugin's parameters. These are fetched once during initialization. That way the
/// `ParamPtr`s are guaranteed to live at least as long as this object and we can interact with /// `ParamPtr`s are guaranteed to live at least as long as this object and we can interact with
/// the `Params` object without having to acquire a lock on `plugin`. /// the `Params` object without having to acquire a lock on `plugin`.
@ -353,7 +353,7 @@ impl<P: ClapPlugin> MainThreadExecutor<Task<P>> for Wrapper<P> {
unsafe fn execute(&self, task: Task<P>) { unsafe fn execute(&self, task: Task<P>) {
// This function is always called from the main thread, from [Self::on_main_thread]. // This function is always called from the main thread, from [Self::on_main_thread].
match task { match task {
Task::PluginTask(task) => (self.task_executor)(task), Task::PluginTask(task) => (self.task_executor.lock())(task),
Task::LatencyChanged => match &*self.host_latency.borrow() { Task::LatencyChanged => match &*self.host_latency.borrow() {
Some(host_latency) => { Some(host_latency) => {
// XXX: The CLAP docs mention that you should request a restart if this happens // XXX: The CLAP docs mention that you should request a restart if this happens
@ -387,7 +387,7 @@ impl<P: ClapPlugin> MainThreadExecutor<Task<P>> for Wrapper<P> {
impl<P: ClapPlugin> Wrapper<P> { impl<P: ClapPlugin> Wrapper<P> {
pub fn new(host_callback: *const clap_host) -> Arc<Self> { pub fn new(host_callback: *const clap_host) -> Arc<Self> {
let plugin = P::default(); let plugin = P::default();
let task_executor = plugin.task_executor(); let task_executor = Mutex::new(plugin.task_executor());
let editor = plugin.editor().map(Mutex::new); let editor = plugin.editor().map(Mutex::new);
// This is used to allow the plugin to restore preset data from its editor, see the comment // This is used to allow the plugin to restore preset data from its editor, see the comment

View file

@ -80,7 +80,7 @@ impl<P: Plugin, B: Backend> GuiContext for WrapperGuiContext<P, B> {
impl<P: Plugin, B: Backend> InitContext<P> for WrapperInitContext<'_, P, B> { impl<P: Plugin, B: Backend> InitContext<P> for WrapperInitContext<'_, P, B> {
fn execute(&self, task: P::BackgroundTask) { fn execute(&self, task: P::BackgroundTask) {
(self.wrapper.task_executor_wrapper.task_executor)(task); (self.wrapper.task_executor_wrapper.task_executor.lock())(task);
} }
fn plugin_api(&self) -> PluginApi { fn plugin_api(&self) -> PluginApi {

View file

@ -141,12 +141,12 @@ impl WindowHandler for WrapperWindowHandler {
/// Adapter to make `TaskExecutor<P>` work as a `MainThreadExecutor`. /// Adapter to make `TaskExecutor<P>` work as a `MainThreadExecutor`.
pub struct TaskExecutorWrapper<P: Plugin> { pub struct TaskExecutorWrapper<P: Plugin> {
pub task_executor: TaskExecutor<P>, pub task_executor: Mutex<TaskExecutor<P>>,
} }
impl<P: Plugin> MainThreadExecutor<P::BackgroundTask> for TaskExecutorWrapper<P> { impl<P: Plugin> MainThreadExecutor<P::BackgroundTask> for TaskExecutorWrapper<P> {
unsafe fn execute(&self, task: P::BackgroundTask) { unsafe fn execute(&self, task: P::BackgroundTask) {
(self.task_executor)(task) (self.task_executor.lock())(task)
} }
} }
@ -156,7 +156,7 @@ impl<P: Plugin, B: Backend> Wrapper<P, B> {
pub fn new(backend: B, config: WrapperConfig) -> Result<Arc<Self>, WrapperError> { pub fn new(backend: B, config: WrapperConfig) -> Result<Arc<Self>, WrapperError> {
let plugin = P::default(); let plugin = P::default();
let task_executor_wrapper = Arc::new(TaskExecutorWrapper { let task_executor_wrapper = Arc::new(TaskExecutorWrapper {
task_executor: plugin.task_executor(), task_executor: Mutex::new(plugin.task_executor()),
}); });
let params = plugin.params(); let params = plugin.params();
let editor = plugin.editor().map(|editor| Arc::new(Mutex::new(editor))); let editor = plugin.editor().map(|editor| Arc::new(Mutex::new(editor)));

View file

@ -117,7 +117,7 @@ impl<P: Vst3Plugin> GuiContext for WrapperGuiContext<P> {
impl<P: Vst3Plugin> InitContext<P> for WrapperInitContext<'_, P> { impl<P: Vst3Plugin> InitContext<P> for WrapperInitContext<'_, P> {
fn execute(&self, task: P::BackgroundTask) { fn execute(&self, task: P::BackgroundTask) {
(self.inner.task_executor)(task); (self.inner.task_executor.lock())(task);
} }
fn plugin_api(&self) -> PluginApi { fn plugin_api(&self) -> PluginApi {

View file

@ -34,7 +34,7 @@ pub(crate) struct WrapperInner<P: Vst3Plugin> {
/// The wrapped plugin instance. /// The wrapped plugin instance.
pub plugin: Mutex<P>, pub plugin: Mutex<P>,
/// The plugin's background task executor closure. /// The plugin's background task executor closure.
pub task_executor: TaskExecutor<P>, pub task_executor: Mutex<TaskExecutor<P>>,
/// The plugin's parameters. These are fetched once during initialization. That way the /// The plugin's parameters. These are fetched once during initialization. That way the
/// `ParamPtr`s are guaranteed to live at least as long as this object and we can interact with /// `ParamPtr`s are guaranteed to live at least as long as this object and we can interact with
/// the `Params` object without having to acquire a lock on `plugin`. /// the `Params` object without having to acquire a lock on `plugin`.
@ -197,7 +197,7 @@ impl<P: Vst3Plugin> WrapperInner<P> {
#[allow(unused_unsafe)] #[allow(unused_unsafe)]
pub fn new() -> Arc<Self> { pub fn new() -> Arc<Self> {
let plugin = P::default(); let plugin = P::default();
let task_executor = plugin.task_executor(); let task_executor = Mutex::new(plugin.task_executor());
let editor = plugin.editor().map(|editor| Arc::new(Mutex::new(editor))); let editor = plugin.editor().map(|editor| Arc::new(Mutex::new(editor)));
// This is used to allow the plugin to restore preset data from its editor, see the comment // This is used to allow the plugin to restore preset data from its editor, see the comment
@ -527,7 +527,7 @@ impl<P: Vst3Plugin> MainThreadExecutor<Task<P>> for WrapperInner<P> {
// function for checking if a to be scheduled task can be handled right there and // function for checking if a to be scheduled task can be handled right there and
// then). // then).
match task { match task {
Task::PluginTask(task) => (self.task_executor)(task), Task::PluginTask(task) => (self.task_executor.lock())(task),
Task::TriggerRestart(flags) => match &*self.component_handler.borrow() { Task::TriggerRestart(flags) => match &*self.component_handler.borrow() {
Some(handler) => { Some(handler) => {
handler.restart_component(flags); handler.restart_component(flags);