Use multiple reader single writer locks for VST3

This would also need to be done on the plugin side.
This commit is contained in:
Robbert van der Helm
2021-12-28 18:51:14 +01:00
parent 2137d79229
commit 1507e4f574
4 changed files with 533 additions and 381 deletions
+3
View File
@@ -31,6 +31,9 @@ Versioning](https://semver.org/spec/v2.0.0.html).
- Fixed VST3 connection point proxies not being disconnected properly. This code
path is not being used for any of the current Linux VST3 hosts, so this did
not yet cause any issues.
- Rewritten the VST3 object handling to prevent some theoretical data races when
the host inserts or removes plug instances while other instances of that
plugin are processing audio.
### Packaging notes
@@ -34,7 +34,7 @@ Vst3ContextMenuProxyImpl::~Vst3ContextMenuProxyImpl() noexcept {
bridge.send_message(
Vst3ContextMenuProxy::Destruct{.owner_instance_id = owner_instance_id(),
.context_menu_id = context_menu_id()});
bridge.unregister_context_menu(owner_instance_id(), context_menu_id());
bridge.unregister_context_menu(*this);
}
tresult PLUGIN_API
File diff suppressed because it is too large Load Diff
+20 -3
View File
@@ -18,6 +18,7 @@
#include <iostream>
#include <map>
#include <shared_mutex>
#include <string>
#include <public.sdk/source/vst/hosting/module.h>
@@ -319,8 +320,7 @@ class Vst3Bridge : public HostBridge {
* is called from the destructor of `Vst3ContextMenuProxyImpl` just before
* the object gets freed.
*/
void unregister_context_menu(size_t object_instance_id,
size_t context_menu_id);
void unregister_context_menu(Vst3ContextMenuProxyImpl& context_menu);
protected:
void close_sockets() override;
@@ -439,6 +439,15 @@ class Vst3Bridge : public HostBridge {
*/
size_t generate_instance_id() noexcept;
/**
* Fetch the plugin instance along with a lock valid for the instance's
* lifetime. This is mostly just to save some boilerplate everywhere. Use
* C++17's structured binding as syntactic sugar to not have to deal with
* the lock handle.
*/
std::pair<Vst3PluginInstance&, std::shared_lock<std::shared_mutex>>
get_instance(size_t instance_id) noexcept;
/**
* Sets up the shared memory audio buffers for a plugin instance plugin
* instance and return the configuration so the native plugin can connect to
@@ -504,7 +513,15 @@ class Vst3Bridge : public HostBridge {
* up.
*/
std::unordered_map<size_t, Vst3PluginInstance> object_instances;
std::mutex object_instances_mutex;
/**
* In theory all object handling is safe iff the host also doesn't do
* anything weird even without locks. The only time a data race can occur is
* when the host removes or inserts a plugin while also interacting with
* other plugins on different threads. Since the lock should never be
* contested, we should also not get a measurable performance penalty from
* making double sure nothing can go wrong.
*/
std::shared_mutex object_instances_mutex;
/**
* Used in `send_mutually_recursive_message()` to be able to execute