Explorar el Código

V0.4.2
1、修改了RingQueue,添加了阻塞入队方式,去掉了返回值方式的非阻塞出队

Apple hace 4 meses
padre
commit
4d9831e291
Se han modificado 2 ficheros con 78 adiciones y 14 borrados
  1. 77 13
      common/RingQueue/RingQueue.hpp
  2. 1 1
      common/ThreadPool/ThreadPool.cpp

+ 77 - 13
common/RingQueue/RingQueue.hpp

@@ -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()

+ 1 - 1
common/ThreadPool/ThreadPool.cpp

@@ -70,7 +70,7 @@ void ThreadPool::worker()
     {
         /* 等待任务队列中有任务 */
         std::unique_lock<std::mutex> lock(m_mutexTask);
-        /* 这里的wait第二个参数是lamba表达式,在唤醒后会进行判断是否满足条件 */
+        /* 这里的wait第二个参数是lamba表达式,被唤醒后再次检查条件是否满足 */
         m_cond_Task.wait(lock, [this]
                                { return !m_queue_Tasks.empty() || m_stop ||
                                         (m_threadExitNum > 0); });