Schedulerspawns and orchestrates multiple threads. Currently the threads managed by
DATAFEEDER_PROCESS, which handles receiving new data from antenna or file,
RESAMPLE, which sets frequency correction when antenna is used,
SYNCHRONIZER_PROCESS, which finds the beginning of the next frame,
DEMODULATOR_PROCESS, which demodulates data,
DATADECODER_PROCESS, which decodes data into audio stream,
AUDIO_PROCESS, which decodes and plays the audio stream.
Scheduler needs to react as soon as possible after each thread finishes processing its part of data. As it is neither possible to wait for signal on multiple
pthread_conds, nor efficient or safe (as it creates a risk of race condition) to iterate over mutexes, a message queue is used.
After given thread finishes processing its data, it pushes its thread ID to the queue. The queue is implemented with a blocking read: if queue is empty, it will block the read until a new message has been added to it. Thanks to that the
Scheduler can continuously pull new messages from the queue without wasting resources.
Each thread stops after processing a batch of data, so it is up to the
Scheduler to decide whether new data is ready to be processed or not, and it is the
Scheduler that needs to notify the thread about that.
Schedulerhave these things in common:
- they need to be told when new data is ready to be processed,
- they need to push message to the queue when they have finished processing data,
- it needs to be possible to check whether thread is currently processing some data.
These things were abstracted away in
SignaledWorkerThread class. To turn any process into thread that supports this signaling, a function with a signature
void process_function(void *) must be created and passed to
SignaledWorkerThread::init() method together with an argument that should be passed to this function, a thread ID and a message queue.
SignaledWorkerThread::resume_thread() is called, the
process_function passed to
init() will be called.
SignaledWorkerThread::is_suspended() will return
process_function returns. When it returns, the thread ID is pushed to message queue and the thread suspends until
resume_thread is called again.