#pragma once
#include <iostream>
#include <condition_variable>
#include <mutex>
#include <queue>
#include <memory>
/*
*
* 线程安全队列
* T为队列元素类型
* 因为有std::mutex和std::condition_variable类成员,所以此类不支持复制构造函数也不支持赋值操作符(=)
*
* 来源: https://blog.csdn.net/u011726005/article/details/82670730
*/
template<class T, class Container = std::queue<T>>
class ThreadSafeQueue {
public:
ThreadSafeQueue() = default;
// 将元素加入队列
template <class Element>
void Push(Element&& element) {
std::lock_guard<std::mutex> lock(mutex_);
queue_.push(std::forward<Element>(element));
not_empty_cv_.notify_one();
}
// 从队列中弹出一个元素,如果队列为空就阻塞
void WaitAndPop(T& t) {
std::unique_lock<std::mutex> lock(mutex_);
not_empty_cv_.wait(lock, [this]() {
return !queue_.empty();
});
t = std::move(queue_.front());
queue_.pop()
}
// 从队列中弹出一个元素,如果队列为空就阻塞
std::shared_ptr<T> WaitAndPop() {
std::unique_lock<std::mutex> lock(mutex_);
not_empty_cv_.wait(lock, [this]() {
return !queue_.empty();
});
std::shared_ptr<T> t_ptr = std::make_shared<T>(queue_.front());
queue_.pop();
return t_ptr;
}
// 从队列中弹出一个元素,如果队列为空返回false
bool TryPop(T& t) {
std::lock_guard<std::mutex> lock(mutex_);
if (queue_.empty()) {
return false;
}
t = std::move(queue_.front());
queue_.pop();
return true;
}
// 从队列中弹出一个元素,如果队列为空返回空指针
std::shared_ptr<T> TryPop() {
std::lock_guard<std::mutex> lock(mutex_);
if (queue_.empty()) {
return std::shared_ptr<T>();
}
t = std::move(queue_.front());
std::shared_ptr<T> t_ptr = std::make_shared<T>(queue_.front());
queue_.pop();
return t_ptr;
}
// 返回队列是否为空
bool IsEmpty() const {
std::lock_guard<std::mutex> lock(mutex_);
return queue_.empty();
}
// 返回队列中元素数个
size_t size() {
std::lock_guard<std::mutex> lock(mutex_);
return queue_.size();
}
private:
ThreadSafeQueue(const ThreadSafeQueue&) = delete;
ThreadSafeQueue& operator=(const ThreadSafeQueue&) = delete;
ThreadSafeQueue(ThreadSafeQueue&&) = delete;
ThreadSafeQueue& operator=(ThreadSafeQueue&&) = delete;
private:
Container queue_;
std::condition_variable not_empty_cv_;
mutable std::mutex mutex_;
};