A channel is a thread-safe queue which uses semaphores to synchronize access. The underlying queue in this implementation is the C++ std::queue container. It uses two semaphores sem_freespaces to count the free spaces in the queue and avoid overflow and semsize to count the elements in the queue and prevent underflow. In addition a std::mutex is used to synchronize access to the queue.
To enqueue an element to the channel the sem_freespaces semaphore is first decremented which will block on a full queue and then increments the semsize semaphore after adding the element to the queue.
Dequeuing works the opposite way by first decrementing semsize to block on an empty queue.
In addition the << operator has been overloaded to move items into the channel or out of it. It also supports moving an item directly from one channel to another.
A destroy function is used to notify waiting threads to shutdown the program. For clarity this is implemented only in a rudimentary way. For full functionality it must be defined what shall happen when the reader blocks on an empty queue and when the writer blocks on a full queue while the system is to be shut down. There are several solutions for this problem which shall be discussed in a further post.