SpinLock in IIRFilter

I know very little about locks but I’ve definitely read enough that they should be avoided in audio code. So I’m wondering, what is the purpose of this SpinLock in the IIRFilter::setCoefficients() function?

void IIRFilter::setCoefficients (const IIRCoefficients& newCoefficients) noexcept
    const SpinLock::ScopedLockType sl (processLock);
    coefficients = newCoefficients;
    active = true;

It’s really just copying 5 floats which I’d expect is a very fast operation, so why the need for the lock?

setCoefficients() is called from the UI thread, the coefficients are read in the audio thread, and IIRCoefficients is not an atomic structure. Without the lock, it would be possible to read a partially-updated set of filter coefficients in the audio thread, which could make the filter state unstable.

A cleaner approach would be to use an atomic pointer swap instead of the spinlock, of course.

Though on Windows the native CriticalSection (which JUCE also uses) is initially a spinlock and after some spinning it does the expensive switch to waiting.

Thanks, didn’t know that. (I withdraw my post because fuzzface expl was so much better than mine!)

that’s how the juce-spinlock works.

I don‘t think that an OS criticalSection works that way, the OS has directly access to the thread scheduler, spinning would actually make the situation worse, because the scheduler would give the spinning even more CPU Power.

I see, it’s for safety when changing the filter from the UI thread. My particular use case is modifying the filter while in the audio thread every 8 samples. So based on that, I could remove the SpinLock…if I’m only modifying it from the audio thread. Yes?

that is a bad design of the filter class. it should be the code that uses the filter which should lock if it access the filter from multiple threads not the filter class itself. also, changing coefficients from the ui without using double buffering… bah

1 Like

That is indeed bad design and should be fixed ASAP.