#pragma
#include <list>
#include <mutex>
#include <condition_variable>
#include <iostream>
#include <chrono>
using namespace std;
const int MaxTaskCount = 200;
template<class T>
class SyncQueue
{
private:
std::list<T> m_queue;
mutable std::mutex m_mutex;
std::condition_variable m_notEmpty;
std::condition_variable m_notFull;
std::condition_variable m_waitStop;
int m_maxSize;
bool m_needStop; //true停止
public:
bool IsFull() const
{
bool full = m_queue.size() >= m_maxSize;
if (full)
{
cout << "m_queue is full, waiting..." << endl;
}
return full;
}
bool IsEmpty() const
{
bool empty = m_queue.empty();
if (empty)
{
cout << "m_queue is empty, waiting..." << endl;
}
return empty;
}
template<class F>
int Add(F&& task)
{
std::unique_lock<std::mutex> lock(m_mutex);
if (!m_notFull.wait_for(lock, std::chrono::seconds(1),
[this]()
{ return m_needStop || !IsFull(); }))//lambda为假弃锁
{
return 1;
}
if (m_needStop)
{
return 2;
}
m_queue.push_back(std::forward<F>(task));
m_notEmpty.notify_all();
return 0;
}
public:
SyncQueue(int maxsize) : m_maxSize(maxsize), m_needStop(false) {}
~SyncQueue() {}
void Put(const T& task)
{
Add(task);
}
void Put(T&& task)
{
Add(std::forward<T>(task));
}
void Take(std::list<T>& tlist)
{
std::unique_lock<std::mutex> lock(m_mutex);
m_notEmpty.wait(lock, [this]()
{ return m_needStop || !IsEmpty(); });
if (m_needStop)
{
return;
}
tlist = std::move(m_queue);
m_notFull.notify_all();
}
void Take(T& task)
{
std::unique_lock<std::mutex> lock(m_mutex);
m_notEmpty.wait(lock, [this]()
{ return m_needStop || !IsEmpty(); });
if (m_needStop)
{
return;
}
task = m_queue.front();
m_queue.pop_back();
m_notFull.notify_all();
}
void Stop()
{
{
std::lock_guard<std::mutex> locker(m_mutex);
m_needStop = true;
}
m_notFull.notify_all();
m_notEmpty.notify_all();
}
void WaitStop()
{
std::unique_lock<std::mutex> locker(m_mutex);
while (!IsEmpty())
{
m_waitStop.wait_for(locker, std::chrono::milliseconds(1));
}
m_needStop = true;
m_notFull.notify_all();
m_notEmpty.notify_all();
}
bool Empty() const
{
std::lock_guard<std::mutex> locker(m_mutex);
return m_queue.empty();
}
bool Full() const
{
std::lock_guard<std::mutex> locker(m_mutex);
return m_queue.size() >= m_maxSize;
}
size_t Size() const {
std::lock_guard<std::mutex> locker(m_mutex);
return m_queue.size();
}
size_t Count() const {
return m_queue.size();
}
};