|
@@ -4,6 +4,7 @@
|
|
|
#include <cstdlib>
|
|
|
#include <utility>
|
|
|
#include <mutex>
|
|
|
+#include <condition_variable>
|
|
|
// #include <atomic>
|
|
|
|
|
|
/**
|
|
@@ -43,11 +44,19 @@ public:
|
|
|
/* 入队 */
|
|
|
bool enQueue(const T& data);
|
|
|
bool enQueue(T&& data);
|
|
|
+ /* 阻塞入队 */
|
|
|
+ void enQueueBlock(const T& data);
|
|
|
/* 出队 */
|
|
|
bool deQueue(T& data);
|
|
|
- T& deQueue();
|
|
|
- /* 获取队列中第一个值(下一个出队的元素),但是不出队 */
|
|
|
- T& front();
|
|
|
+ /* 阻塞出队 */
|
|
|
+ T& deQueueBlock();
|
|
|
+
|
|
|
+ /* 获取队列中第一个值(下一个出队的元素),但是不出队,非阻塞 */
|
|
|
+ bool front(T& t);
|
|
|
+ T& frontBlock();
|
|
|
+ /* 获取队列中即将入队的位置(这个函数用于存储指针的环形队列,获取内存地址) */
|
|
|
+ T& backBlock();
|
|
|
+
|
|
|
/* 获取队列大小,队列中有效值的大小 */
|
|
|
long getQueueSize();
|
|
|
/* 获取队列容量 */
|
|
@@ -63,6 +72,8 @@ private:
|
|
|
long m_capacity = 0; /* 队列容量 */
|
|
|
long m_front = 0; /* 队头 */
|
|
|
long m_rear = 0; /* 队尾 */
|
|
|
+ std::condition_variable m_cond_NoFull; /* 非空条件变量 */
|
|
|
+ std::condition_variable m_cond_NoEmpty; /* 非满条件变量 */
|
|
|
};
|
|
|
|
|
|
|
|
@@ -140,6 +151,7 @@ bool RingQueue<T>::enQueue(const T& data)
|
|
|
m_rear = (m_rear + 1) % m_capacity;
|
|
|
|
|
|
m_mutex.unlock();
|
|
|
+ m_cond_NoEmpty.notify_all();
|
|
|
return true;
|
|
|
}
|
|
|
|
|
@@ -163,9 +175,31 @@ bool RingQueue<T>::enQueue(T&& data)
|
|
|
m_rear = (m_rear + 1) % m_capacity;
|
|
|
|
|
|
m_mutex.unlock();
|
|
|
+ m_cond_NoEmpty.notify_all();
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
+/* 阻塞入队 */
|
|
|
+template<typename T>
|
|
|
+void RingQueue<T>::enQueueBlock(const T& data)
|
|
|
+{
|
|
|
+ m_mutex.lock();
|
|
|
+ m_cond_NoFull.wait(m_mutex, [this](){
|
|
|
+ return !isFull();
|
|
|
+ });
|
|
|
+
|
|
|
+ if(m_rear == -1)
|
|
|
+ {
|
|
|
+ m_front = 0;
|
|
|
+ m_rear = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ m_queue[m_rear] = data;
|
|
|
+ m_rear = (m_rear + 1) % m_capacity;
|
|
|
+ m_mutex.unlock();
|
|
|
+ m_cond_NoEmpty.notify_all();
|
|
|
+}
|
|
|
+
|
|
|
/* 出队 */
|
|
|
template<typename T>
|
|
|
bool RingQueue<T>::deQueue(T& data)
|
|
@@ -186,18 +220,19 @@ bool RingQueue<T>::deQueue(T& data)
|
|
|
}
|
|
|
|
|
|
m_mutex.unlock();
|
|
|
+ m_cond_NoFull.notify_all();
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
/* 出队 */
|
|
|
template<typename T>
|
|
|
-T& RingQueue<T>::deQueue()
|
|
|
+T& RingQueue<T>::deQueueBlock()
|
|
|
{
|
|
|
std::lock_guard<std::mutex> lock(m_mutex);
|
|
|
- if(isEmpty())
|
|
|
- {
|
|
|
- return T();
|
|
|
- }
|
|
|
+ m_cond_NoEmpty.wait(lock, [this](){
|
|
|
+ return !isEmpty();
|
|
|
+ });
|
|
|
+
|
|
|
long tmp = m_front;
|
|
|
m_front = (m_front + 1) % m_capacity;
|
|
|
if(m_front == m_rear)
|
|
@@ -205,23 +240,52 @@ T& RingQueue<T>::deQueue()
|
|
|
m_front = -1;
|
|
|
m_rear = -1;
|
|
|
}
|
|
|
-
|
|
|
+ m_cond_NoFull.notify_all();
|
|
|
return std::move(m_queue[tmp]);
|
|
|
}
|
|
|
|
|
|
-/* 获取队列中第一个值(下一个出队的元素),但是不出队 */
|
|
|
+/* 获取队列中第一个值(下一个出队的元素),但是不出队,非阻塞 */
|
|
|
template<typename T>
|
|
|
-T& RingQueue<T>::front()
|
|
|
+bool RingQueue<T>::front(T& t)
|
|
|
{
|
|
|
std::lock_guard<std::mutex> lock(m_mutex);
|
|
|
if(isEmpty())
|
|
|
{
|
|
|
- return T();
|
|
|
+ return false;
|
|
|
}
|
|
|
-
|
|
|
+ t = m_queue[m_front];
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
+/* 阻塞获取队列中第一个数据,但是不出队 */
|
|
|
+template<typename T>
|
|
|
+T& RingQueue<T>::frontBlock()
|
|
|
+{
|
|
|
+ std::lock_guard<std::mutex> lock(m_mutex);
|
|
|
+ m_cond_NoEmpty.wait(lock, [this](){
|
|
|
+ return !isEmpty();
|
|
|
+ });
|
|
|
return m_queue[m_front];
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * @brief 获取队列中即将入队的位置(这个函数用于存储指针的环形队列,获取内存地址)
|
|
|
+ * 这个函数不一定内存安全,谨慎使用
|
|
|
+ *
|
|
|
+ * @tparam T
|
|
|
+ * @return T&
|
|
|
+ */
|
|
|
+template<typename T>
|
|
|
+T& RingQueue<T>::backBlock()
|
|
|
+{
|
|
|
+ std::lock_guard<std::mutex> lock(m_mutex);
|
|
|
+ m_cond_NoFull.wait(lock, [this](){
|
|
|
+ return !isFull();
|
|
|
+ });
|
|
|
+
|
|
|
+ return m_queue[m_rear];
|
|
|
+}
|
|
|
+
|
|
|
/* 获取队列中有效值的大小 */
|
|
|
template<typename T>
|
|
|
long RingQueue<T>::getQueueSize()
|