I have read and watched much excellent discussion on the topic of recommended data structures (i.e. ValueTrees & ValueTreeObjectList) and how they may be shared between threads. This, of course, inevitably leads to consideration of prohibitions on what can and cannot (or rather should and should not) be done on real-time threads (i.e. the audio thread).
I think I have just about grasped it, and could probably do a poor man’s job of setting it down here, but in the interests of time and space I will forego that and get right to my question.
One of the takeaways I have from @dave96’s ValueTree discussion (@ 36:20) is that we should avoid creating locks on the audio thread. This is re-iterated in his later talk with @fr810 when we are encouraged to (in some situations) use try_lock
instead of obtaining a full lock, and then we are further advised (@ 42:50) to ensure we use a SpinLock
rather than a regular std::mutex
.
All good so far, but then I wanted to see an example and started poking around @dave96’s GitHub repositories
to see if I could find anything and stumbled upon this which includes the following:
void PitchDetectorComponent::processBlock (const float* inputChannelData, int numSamples)
{
const ScopedLock sl (detectorLock); // [1] <<< I thought we shouldn't do this...?
pitchDetector.processSamples (inputChannelData, numSamples);
pitch = pitchDetector.getPitch();
}
…in which we can see that the first thing that happens in processBlock()
is to create a ScopedLock
(which for completeness is defined in the corresponding header file as a CriticalSection
).
I don’t want to put @dave96 on the spot (I guess I already did that, though…), but I did rather think that following the breadcrumbs of a single individual might help me end up in the same place and this apparent conflict has thrown me for a loop. I totally understand the nature of examples as well as how best practice is formulated over time (that particular file was last modified 4 years prior to the first presentation I referred to above), but to help my tired old brain I’d like to know:
- Would the current recommendation would be not to obtain the
ScopedLock
withinprocessBlock()
but rather consider attempting atry_lock
on aSpinLock
? (For my particular use case I had determined after watching the second presentation and it’sfollowing partner that this would be right for me).
…or… - Is there something I have missed or misunderstood in all I have recently consumed that means this is actually a correct approach for this particular use case?
Thanks so much in advance, and thanks also to @dave96, @fr810 and all the others too numerous to mention who have debated, presented and documented this topic at significant length for the enormous educational benefit of those who, like me, have come to the game later.