-
-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Possible race condition? #6
Comments
Should be fine, the DSP side is the owner/server of the shared memory, the UI side simply connects to it. the code for this is in https://github.com/DISTRHO/OneKnob-Series/blob/main/plugins/common/SharedMemory.hpp I have been using this same approach for plugin bridges in carla, no issues in there so far. |
I agree that is the right approach, but this part got me confused OneKnob-Series/plugins/common/OneKnobUI.hpp Line 311 in 7951033
Isn't the UI controlling the shared memory lifetime in this case? |
Indeed, I have the logic for this wrong.
I was trying to avoid creating a shm segment if the UI is never open, but this is the wrong approach for sure. |
I stumbled upon this scenario independently, I could not find a way to make the Plugin own the shared memory because that would require notifying the UI about the filename. AFAIK state updates are only possible in the UI->Plugin direction and not the other way around, unless the filename is set as a defaultStateValue. But defaultStateValue is a no-go because on VST3 the Plugin constructor runs 3 times and UI gets the defaultStateValue from instance no. 2, which is not finally the one running the DSP. That hack works with CLAP though. BTW is it by design that VST3 creates multiple Plugin instances? I thought finishing Plugin::updateStateValue() could help solving this problem. It is currently marked as TODO API under construction. |
This is being worked on in develop branch, and already in use for Cardinal.
Yes, unless you set instance-access to 1. In order to get proper DSP/UI separation for VST3, due to their weird component vs controller vs view architecture, we need to create 2 DSP objects. 1 is associated with the component, the other with the controller. then view gets the UI stuff. |
Cool, will give |
This synchronization pseudocode could be helpful until the missing state method is completed, it relies on a std::atomic_flag. It works nice for my project: #include <atomic>
// UI side (shmem owner)
SomeUI::~SomeUI()
{
setState("shared_mem", "the_owner_will_destroy_it"); // blocks if needed
fSharedMemory.close();
}
// Plugin side (shmem client)
SomePlugin::setState(const char* key, const char* value)
{
if (std::strcmp("shared_mem", "the_owner_will_destroy_it") == 0) {
if (fShMemIsBusy.test_and_set()) {
// Flag was already true, the shared memory is busy.
// Wait for the current render cycle to release it.
while (fShMemIsBusy.test_and_set()) {};
// Flag cleared, now set again to true, free to proceed.
} else {
// Flag was false but now is true, free to proceed.
}
// Do the dangerous business
fSharedMemory.close();
// Done
fShMemIsBusy.clear();
}
}
void SomePlugin::run(const float** inputs, float** outputs, uint32_t frames)
{
if (fShMemIsBusy.test_and_set()) {
// Shared memory is being closed
} else {
// Safe to access shared memory
if (fSharedMemory.isCreatedOrConnected()) {
...
}
// Release
fShMemIsBusy.clear();
}
...
} EDIT : updated the state value string for clarity |
What is |
Yes, it is a member of the Plugin instance, the snippet is not clear in that sense but does not enforce the shared memory to hold any data in particular. |
class SomePlugin : public Plugin
{
...
private:
SharedMemory<...> fSharedMemory;
std::atomic_flag fShMemIsBusy;
...
}; |
right, so for testing that could work in theory but I advise to NOT use anything with constructors and other stuff when going with shared memory. if you see how the float-fifo thing works on this repo, there is a clear separation between POD data and the C++ class that controls it. so we can have the data/buffer on shared memory, but still have conveniences of C++ working on top of it. |
Do you mean the In my project, there is a VisualizationData class and the plugin uses placement Anyways, regardless the logic for accessing the shared memory, the key challenge seems to be making sure Plugin does not attempt to |
I can think of cases where UI and DSP do not match in terms of build options, packing or even architecture, and thus the non-POD data would not match. For Carla I have plugin bridges with different architectures, so the shm data must match between them, which poses a small headache at times. |
That is a good point to keep in mind, thanks. |
Isn't there a risk of writing to an invalid location if the UI was closed exactly at this point? and hence the shared memory referenced by FloatFifoControl, deleted.
OneKnob-Series/plugins/common/OneKnobPlugin.hpp
Line 139 in 26ca598
The text was updated successfully, but these errors were encountered: