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_free_spaces_ to count the free spaces in the queue and avoid overflow and sem_size_ 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_free_spaces_ semaphore is first decremented which will block on a full queue and then increments the sem_size_ semaphore after adding the element to the queue.
Dequeuing works the opposite way by first decrementing sem_size_ 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.