| #pragma once | |
| #include <condition_variable> | |
| #include <deque> | |
| #include <mutex> | |
| // Copied from | |
| // https://morestina.net/blog/1400/minimalistic-blocking-bounded-queue-for-c | |
| template <typename T> class queue | |
| { | |
| std::deque<T> content; | |
| size_t capacity; | |
| std::mutex mutex; | |
| std::condition_variable not_empty; | |
| std::condition_variable not_full; | |
| queue(const queue&) = delete; | |
| queue(queue&&) = delete; | |
| queue& operator=(const queue&) = delete; | |
| queue& operator=(queue&&) = delete; | |
| public: | |
| queue(size_t capacity) : capacity(capacity) {} | |
| void push(T&& item) | |
| { | |
| { | |
| std::unique_lock<std::mutex> lk(mutex); | |
| not_full.wait(lk, [this]() { return content.size() < capacity; }); | |
| content.push_back(std::move(item)); | |
| } | |
| not_empty.notify_one(); | |
| } | |
| bool try_push(T&& item) | |
| { | |
| { | |
| std::unique_lock<std::mutex> lk(mutex); | |
| if (content.size() == capacity) | |
| return false; | |
| content.push_back(std::move(item)); | |
| } | |
| not_empty.notify_one(); | |
| return true; | |
| } | |
| void pop(T& item) | |
| { | |
| { | |
| std::unique_lock<std::mutex> lk(mutex); | |
| not_empty.wait(lk, [this]() { return !content.empty(); }); | |
| item = std::move(content.front()); | |
| content.pop_front(); | |
| } | |
| not_full.notify_one(); | |
| } | |
| bool try_pop(T& item) | |
| { | |
| { | |
| std::unique_lock<std::mutex> lk(mutex); | |
| if (content.empty()) | |
| return false; | |
| item = std::move(content.front()); | |
| content.pop_front(); | |
| } | |
| not_full.notify_one(); | |
| return true; | |
| } | |
| }; |