Static int insideVSTCallback = 0;


#1

Why is this static? What happens if two different threads call into two different VST plugin instances at the same time?


#2

If I remember correctly, it’s there to catch recursion in the event thread callbacks (e.g. host calls a plugin function, which calls hostIdle, which then calls another plugin function). That could happen between plugin instances, so it’s static, and should only happen on the event thread.


#3

Hmm…I’m a little confused then. Check this out:

[code]int VSTPluginInstance::dispatch (const int opcode, const int index, const int value, void* const ptr, float opt) const
{
const ScopedLock sl (lock);

++insideVSTCallback;[/code]

What if there are two VSTPluginInstance objects, each in their own thread, going through dispatch()?

The only places that insideVSTCallback is actually checked are:

VSTPluginInstance::~VSTPluginInstance()
{
    const ScopedLock sl (lock);
    jassert (insideVSTCallback == 0);

and

    case audioMasterIdle:
        if (insideVSTCallback == 0 && MessageManager::getInstance()->isThisTheMessageThread())
        {
            ++insideVSTCallback;

I almost always get that assertion in ~VSTPluginInstance(). I have multiple plugs in multiple threads.

For both of these cases it would make sense for the VSTPluginInstance to have insideVSTCallback be a non-static member. The treatment of loading the .DLL would have to be managed (it accesses insideVSTCallback but is not associated with an instance of VSTPluginInstance).

Thoughts?


#4

hmm…do I have to do something special in my host application? I create the plugin on a separate dedicated thread (to avoid slowing down the audio i/o callback) and then I call the process function from the audio i/o callback.

How does the plugin gain access to the message thread? Do I have to add support for hostIdle ?


#5

OH…

…okay I think I understand now Jules!

I believe what we need is to change

to

and add

to VSTPluginInstance(). Then, every member of VSTPluginInstance that currently does

should become

if (++insideVSTCallback == 1)
  ++globalInsideVSTCallback;

And of course the corresponding code for decrementing:

if (--insideVSTCallback == 0)
  --globalInsideVSTCallback;

This will fix the assert in the destructor. The case for audioMasterIdle would use globalInsideVSTCallback instead of insideVSTCallback.

Whaddyathink?


#6

Creating plugins on background threads can cause problems… I had a lot of trouble because Wavelab does that - see my rants about it on other threads.

Looking at it again, the safeguard could probably be implemented better - the whole point was to prevent the idle callbacks becoming recursive, so a thread-local variable would be ideal… Or maybe it could be used to protect a smaller section of the code, which won’t be called in a multi-threaded context. Will have a look.


#7

Uuuuggghhh…I feel a headache coming on…is there a consolidated “best practices” for hosts I can read up on? Where are these threads?