Skip to content

Instantly share code, notes, and snippets.

@yaraki
Created February 17, 2015 15:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yaraki/96beed0a48d9f8122d4a to your computer and use it in GitHub Desktop.
Save yaraki/96beed0a48d9f8122d4a to your computer and use it in GitHub Desktop.
Go-style channel in C++
#include <iostream>
#include <list>
#include <thread>
namespace ya {
template<class item_t>
class channel {
private:
std::list<item_t> items_;
std::mutex mutex_;
std::condition_variable condition_;
bool closed_;
size_t size_limit_;
public:
channel(size_t max) : closed_(false), size_limit_(max) {
}
channel() : channel(SIZE_MAX) {
}
void close() {
std::unique_lock<std::mutex> lock(mutex_);
closed_ = true;
condition_.notify_all();
}
bool is_closed_() {
std::unique_lock<std::mutex> lock(mutex_);
return closed_;
}
void put(const item_t &i) {
std::unique_lock<std::mutex> lock(mutex_);
if (closed_) {
throw std::logic_error("Put to a closed channel");
}
condition_.wait(lock, [&]() {
return items_.size() < size_limit_;
});
items_.push_back(i);
condition_.notify_one();
}
bool get(item_t &out, bool wait = true) {
std::unique_lock<std::mutex> lock(mutex_);
if (wait) {
condition_.wait(lock, [&]() {
return closed_ || !items_.empty();
});
}
if (items_.empty()) { // closed
return false;
}
out = items_.front();
items_.pop_front();
condition_.notify_one();
return true;
}
};
}
int main()
{
ya::channel<int> c(1);
auto t = std::thread([&c]() {
for (int i = 0; i < 10; ++i) {
c.put(i);
}
c.close();
});
int a;
while (c.get(a)) {
std::cout << a << std::endl;
}
t.join();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment