Hey Jules -
I’ve been employing value objects a lot lately, and finally started to run up against a few errors that I don’t quite understand.
Since Value objects are not thread safe, I’ve got a subclass that has a CriticalSection which gets locked before any getValue or setValue operations. I had thought this would be enough to get them to be fully threadsafe, but I’m starting to realize this may not be the case.
The objects are fine nearly all the time, but there are some issues that arise because the Message Manager thread sometimes accesses the Value objects (I think).
So for example … If I am understanding correctly …
Here is an issue where two threads both try to access the object: on one, a midi message has come in that is mapped to some value object, so it has locked the CriticalSection and altered the value. It is now trying to send a message.
The other thread (the MM) is going through it’s messages, has found one related to this ValueObject and is calling all the listeners.
Anyway, you can see the issue. My question, really, is whether it is feasible to use Value objects in a multithreaded environment at all? or if I should write some custom shared var objects that lock more often.
yes, that kind of thing is inevitable really, you could only fully lock it using a MessageManagerLock. That’s not something you can use in a realtime thread, but a normal lock isn’t particular good in a midi callback either. Why not make your midi thread just push its incoming messages into a queue, and then have a Timer or other message-thread event that picks them up and does whatever’s needed with them?
Hmmm … so really, using Value::getValue() in a Audio callback at all is a huge problem too, huh? That’s unfortunate since I’ve been using it everywhere up until now.
It’s only because of the changeMessage though? Could we perhaps use a setValue(value, changeNotificationType) method that would let us specify NOT to send a message?
Well, that’s something I could add, but I still wouldn’t recommend setting Value objects in an audio thread. You might just about to get away with reading them if you’re lucky, but I doubt whether you could set them safely.
Anyway, if you have a Value which doesn’t send out any change messages when you set it, then it doesn’t need to be a Value at all - you might as well just use a float or something.
True. The thing I like about the Value is, of course, the changeMessages.
It occurs to me that the way to do it is to have a float that represents the actual most current value, and just update the Value object on the timer thread. I could then override the getValue to only use the Value::getValue when called from the MM thread, and just return the currentValue float otherwise.
A little hacky, but seems like it should work. It’s just so nice to link the UI Value objects directly to parameters which are also used in the audio callbacks.
Anyway, thanks for the guidance as usual.
Now get those plugins working with openGL … haha
You can actually already do this by creating a ValueSource similar to SimpleValueSource that just doesn’t send a change message, or sends one synchronously. However, I agree with Jules that you probably don’t want to be accessing Values from your audio callback. I normally designate Values and ValueTrees as message thread only, deferring updates using a queue and then have some kind of synchronise callback that updates the parameters I’m actually using ing the audio callback as these are usually different to what you’re displaying in the UI or exposing as parameters anyway.
yup, thats basically what I’ve done.
Works like a charm, thanks!