Second, I learned about circular buffer. I wonder if it is suitable solution? |
A
circular buffer is commonly used to exchange data between concurrent threads. Simply put, one thread, the "producer",
writes its generated data into the slots in sequential order, while the other thread, the "consumer",
reads the data from the slots that have been filled, also in sequential order. Once all slots have been used up, the "producer" wraps around and starts overwriting the slots from the start.
But: The
circular buffer still requires proper synchronization! You have to make sure that the "consumer" thread does
not read a slot
before that slot has been filled by the "producer" thread. Similarly, you have to make sure that the "producer" thread does
not overwrite a slot
before that slot has been fully read by the "consumer" thread. A specific slot
must not be accessed by multiple threads at the same time!
A standard approach to synchronize a
circular buffer is by using two
semaphores: One for counting the "free" slots, and another one for counting the "used" slots. The
producer thread waits until the "free" counter becomes non-zero, then decrements the "free" counter, writes its data into the next slot, and finally increments the "used" counter. Similarly, the
consumer thread waits until the "used" counter becomes non-zero, then decrements the "used" counter, reads the data from the next slot, and finally increments the "free" counter.
It's important to note that, when it comes to
semaphores, the "wait until counter becomes non-zero" action and the "decrement counter" action actually
must happen as a single
atomic operation, in order to avoid race conditions!