Channel Buffering in C++

By default, C++ doesn’t have built-in channels like Go. However, we can simulate a buffered channel using a thread-safe queue from the C++ Standard Library. Here’s an example that demonstrates a similar concept:

#include <iostream>
#include <queue>
#include <mutex>
#include <condition_variable>
#include <thread>

template<typename T>
class BufferedChannel {
private:
    std::queue<T> queue_;
    mutable std::mutex mutex_;
    std::condition_variable not_full_;
    std::condition_variable not_empty_;
    size_t capacity_;

public:
    BufferedChannel(size_t capacity) : capacity_(capacity) {}

    void send(const T& value) {
        std::unique_lock<std::mutex> lock(mutex_);
        not_full_.wait(lock, [this]() { return queue_.size() < capacity_; });
        queue_.push(value);
        not_empty_.notify_one();
    }

    T receive() {
        std::unique_lock<std::mutex> lock(mutex_);
        not_empty_.wait(lock, [this]() { return !queue_.empty(); });
        T value = queue_.front();
        queue_.pop();
        not_full_.notify_one();
        return value;
    }
};

int main() {
    // Here we create a buffered channel of strings with capacity 2
    BufferedChannel<std::string> messages(2);

    // Because this channel is buffered, we can send these
    // values into the channel without a corresponding
    // concurrent receive.
    messages.send("buffered");
    messages.send("channel");

    // Later we can receive these two values as usual.
    std::cout << messages.receive() << std::endl;
    std::cout << messages.receive() << std::endl;

    return 0;
}

This C++ code simulates a buffered channel using a BufferedChannel class. The class uses a std::queue to store the buffered values, along with mutexes and condition variables to ensure thread-safety and proper synchronization.

In the main function, we create a BufferedChannel of strings with a capacity of 2. We then send two strings into the channel without needing a corresponding receive operation immediately. Later, we receive and print these two values.

To compile and run this program:

$ g++ -std=c++17 -pthread channel_buffering.cpp -o channel_buffering
$ ./channel_buffering
buffered
channel

This example demonstrates how we can implement a concept similar to Go’s buffered channels in C++. While C++ doesn’t have built-in channel support, we can create similar constructs using the language’s concurrency primitives and standard library components.