Created
February 17, 2015 15:11
-
-
Save yaraki/96beed0a48d9f8122d4a to your computer and use it in GitHub Desktop.
Go-style channel in C++
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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