My case is specifically for the Audio thread being the consumer of the lock-free queue, but I believe the question is abstract-enough for a General JUCE discussion.
I want to implement correctly (and in that - lock-free) the communication back to the producer thread(s).
There a couple of states that my consumer thread needs to, somehow, expose to the producer:
- NeedProduction;
- ContinueOnPreviousAction;
- StopProducing.
What I’m currently working on seems… wrong. I am using AbstractFifo, not only for the main production, but I use 1, with size 1, to expose the current state of the consumer.
So, I have a code like this in every consumer (which in my current case is called DFDChannel and 1 such channel resides in each voice of a sampler instrument - 1 per voice):
DFDChannel.h:
enum DFDChannelRequest {
NoNewActionRequired,
SamplesNeeded,
StopStreaming
};
class DFDChannel : public IChannel
{
public:
DFDChannel (const int buffChCount, const int buffSize/*, ...*/)
: bufferSize (buffSize),
bufferChannelCount (buffChCount),
// ...
buffer (bufferChannelCount, bufferSize),
incomingFifo (buffSize),
outgoingFifo (1),
// ...
{}
/* Called by Audio Rendering Thread */
void start (LayeredSamplerSound* snd) override;
void stop () override;
int fillBuffer (AudioSampleBuffer& buffer, int numSamples, int sampleIndex) override;
/* Called by DFD Thread */
int writeSamplesToChannel (AudioSampleBuffer& buffer);
DFDChannelRequest getServerRequest ();
private:
int bufferSize;
int bufferChannelCount;
// ...
AudioSampleBuffer buffer;
AbstractFifo incomingFifo;
AbstractFifo outgoingFifo;
DFDChannelRequest serverRequest;
// ...
/* Called by Audio Rendering Thread */
void setServerRequest (DFDChannelRequest request);
// ...
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DFDChannel);
};
DFDChannel.cpp:
// ...
void DFDChannel::setServerRequest (DFDChannelRequest request)
{
int start1, size1, start2, size2;
int itemsCount = 1;
// overwrite the previous, if one exist
outgoingFifo.reset ();
outgoingFifo.prepareToWrite (itemsCount, start1, size1, start2, size2);
int requestsWrittenCount = size1 + size2;
jassert (requestsWrittenCount > 0);
serverRequest = request;
outgoingFifo.finishedWrite (requestsWrittenCount);
}
DFDChannelRequest DFDChannel::getServerRequest ()
{
int start1, size1, start2, size2;
int itemsCount = 1;
outgoingFifo.prepareToRead (itemsCount, start1, size1, start2, size2);
int requestsReadCount = size1 + size2;
DFDChannelRequest result = serverRequest;
if (requestsReadCount == 0)
{
// set the default request
result = DFDChannelRequest.NoNewActionRequired;
}
outgoingFifo.finishedRead (requestsReadCount);
return result;
}
// ...
Any help is much appreciated.
Cheers!