Files
nf7/common/queue.hh
2022-05-21 13:18:11 +09:00

82 lines
1.6 KiB
C++

#pragma once
#include <condition_variable>
#include <deque>
#include <functional>
#include <mutex>
#include <optional>
namespace nf7 {
// thread-safe std::deque wrapper
template <typename T>
class Queue {
public:
Queue() = default;
Queue(const Queue&) = default;
Queue(Queue&&) = default;
Queue& operator=(const Queue&) = default;
Queue& operator=(Queue&&) = default;
void Push(T&& task) noexcept {
std::unique_lock<std::mutex> _(mtx_);
tasks_.push_back(std::move(task));
}
std::optional<T> Pop() noexcept {
std::unique_lock<std::mutex> k(mtx_);
if (tasks_.empty()) return std::nullopt;
auto ret = std::move(tasks_.front());
tasks_.pop_front();
k.unlock();
return ret;
}
protected:
std::mutex mtx_;
private:
std::deque<T> tasks_;
};
// Queue<T> with Wait() method
template <typename T>
class WaitQueue : private Queue<T> {
public:
WaitQueue() = default;
WaitQueue(const WaitQueue&) = default;
WaitQueue(WaitQueue&&) = default;
WaitQueue& operator=(const WaitQueue&) = default;
WaitQueue& operator=(WaitQueue&&) = default;
void Push(T&& task) noexcept {
Queue<T>::Push(std::move(task));
cv_.notify_all();
}
using Queue<T>::Pop;
void Notify() noexcept {
cv_.notify_all();
}
void Wait() noexcept {
std::unique_lock<std::mutex> k(mtx_);
cv_.wait(k);
}
void WaitFor(auto dur) noexcept {
std::unique_lock<std::mutex> k(mtx_);
cv_.wait_for(k, dur);
}
void WaitUntil(auto time) noexcept {
std::unique_lock<std::mutex> k(mtx_);
cv_.wait_until(k, time);
}
private:
using Queue<T>::mtx_;
std::condition_variable cv_;
};
} // namespace nf7