I have five consumers and one producer. The five consumers each output different data, from the one producer, for ~10ms. During those 10ms the producer prepares the parameters for the next output. When the output parameters are set, I want to set a flag instructing the consumers to begin the next output. I only want the producer to produce when the consumers are outputting the data.
I am unsure how to synchronize the five consumers and the single producer. I currently have two flags, runFlag and doneFlag. When a consumer reads the new data I want to set runFlag to true so the calculations begin, and I want to set doneFlag to false, as the calculations have not completed. However, if I set doneFlag to false in one consumer it may be false in another consumer before that consumer can check the flag.
I hope my question is specific enough. Please let me know if there's anything else I can provide. Also, I'm just looking for a general idea of how to proceed. I know there are multiple ways to do this, but I'm unsure which method will work the best.
You will need 2 events and an integer reference count.
When producer has produced some thing it:
- initiates read_count = 0;
- sets event
- starts to wait on event completed;
Consumers wait on event
readme. After doing their work they ATOMICALLY increment
read_count. If the read_count reaches the number of consumers, 5 in your case, then it sets the
completed event. Thus producer can continue and the cycle repeats itself.
A few years back, I had to create a generic work dispatcher that does post-processing. Its not a producer-consumer exactly and may be overkill for your app, but it may give you some ideas.
I particularly like using a pair of in-memory shared queues, an outbound queue and an inbound queue, arranged like a two-way channel. If you create a queue class that has the proper synchronization for reading and writing, the producer and consumers can become independent. They don't need to know how to synchronize with each other.
Your data, known to the producer and consumer, referenced in a work item class. The work item class contains all of the status flags. The data should also be thread safe.
The producer enqueues work items onto the outbound queue and each consumer dequeues a single work item. When the work is completed, the status flags are updated and the work item is posted back to inbound queue for post-processing by the producer.
IIRC, the architecture only contain three classes or so.