#ifndef __BLOCKQUEUE_H__
#define __BLOCKQUEUE_H__
#include <condition_variable>
#include <mutex>
#include <queue>
#include <vector>
#include <assert.h>
#include <iostream>
#include <thread>
using namespace std;
using namespace std::chrono_literals;
/********************************************************************************
类名 : BlockQueue
Description: 阻塞队列模板类,用于生产者消费者场景
Example: BlockQueue<T> oQueue()
*******************************************************************************/
template<typename T>
class BlockQueue {
public:
// make class non-copyable
BlockQueue(const BlockQueue<T>&) = delete;
BlockQueue& operator=(const BlockQueue<T>&) = delete;
/**
* @brief 构造函数,可设置队列大小
*
* @param[in] maxSize 队列大小
* @return 无
*/
explicit BlockQueue<T>(size_t maxSize = INT_MAX)
: m_nMaxSize(maxSize), m_bQuit(false)
{
}
/**
* @brief 向队列里添加对象,可设置超时时间
*
* @param[in] x 添加的对象
* @param[in] timeout 超时时间
* @return true 成功; false 失败
*/
bool push(const T& x, int timeout = INT_MAX)
{
if (m_bQuit) {
return false;
}
std::unique_lock<std::mutex> locker(m_Mutex);
m_NotFullCV.wait_for(locker, timeout*1s,
[this]() {return (m_queue.size() < m_nMaxSize) || m_bQuit;});
if (m_bQuit || m_queue.size() == m_nMaxSize) {
return false;
}
m_queue.push(x);
m_NotEmptyCV.notify_one();
return true;
}
/**
* @brief 从队列里获取对象,可设置超时时间
*
* @param[out] x 获取的对象
* @param[in] timeout 超时时间
* @return true 成功; false 失败
*/
bool pop(T& outRes, int timeout = INT_MAX)
{
if (m_bQuit) {
return false;
}
std::unique_lock<std::mutex> locker(m_Mutex);
m_NotEmptyCV.wait_for(locker, timeout*1s,
[this]() {return !m_queue.empty() || m_bQuit;} );
if (m_bQuit || m_queue.empty()) {
return false;
}
outRes = m_queue.front();
m_queue.pop();
m_NotFullCV.notify_one();
return true;
}
// 获取队列是否为空
bool empty() const
{
std::unique_lock<std::mutex> locker(m_Mutex);
return m_queue.empty();
}
// 获取队列当前容量
size_t size() const
{
std::unique_lock<std::mutex> locker(m_Mutex);
return m_queue.size();
}
// 返回队列最大容量
size_t maxSize() const
{
return m_nMaxSize;
}
// 退出,以便阻塞的pop和push能够返回
void quit()
{
m_bQuit = true;
m_NotEmptyCV.notify_all();
m_NotFullCV.notify_all();
}
private:
mutable std::mutex m_Mutex;
std::condition_variable m_NotEmptyCV;
std::condition_variable m_NotFullCV;
size_t m_nMaxSize;
std::queue<T> m_queue;
bool m_bQuit;
};
#endif