Browse Source

V0.4.9
1、重做了RingQueue,修改了函数功能名称以及入队和出队的方式

Apple 4 months ago
parent
commit
ae3eb9f66c
1 changed files with 217 additions and 129 deletions
  1. 217 129
      common/RingQueue/RingQueue.hpp

+ 217 - 129
common/RingQueue/RingQueue.hpp

@@ -9,10 +9,12 @@
 
 
 /**
 /**
  * @brief 这里采用零公摊的方式,设置多大的空间,就有多大的空间可以使用
  * @brief 这里采用零公摊的方式,设置多大的空间,就有多大的空间可以使用
- *        1、如果队列是空,m_rear和m_front都设置为-1
- *        2、m_rear指向最新入队的元素的下一个位置
- *        3、m_front指向需要出队的第一个元素
- *        4、环形队列自带互斥锁
+ *        1、m_rear指向最新入队的元素的下一个位置,就是下个将要入队的元素位置
+ *        2、m_front指向需要出队的第一个元素
+ *        3、环形队列自带互斥锁
+ *        
+ * 注意:
+ *      使用时要注意,不带NoBlock的都是阻塞函数
  *
  *
  * 判断队列满:
  * 判断队列满:
  *        m_rear == m_front,并且此时都不等于 -1
  *        m_rear == m_front,并且此时都不等于 -1
@@ -32,7 +34,7 @@
 
 
 template<typename T>
 template<typename T>
 class RingQueue
 class RingQueue
-{
+{    
 
 
 public:
 public:
     RingQueue();
     RingQueue();
@@ -45,22 +47,28 @@ public:
     /* 清空队列 */
     /* 清空队列 */
     void clearQueue();
     void clearQueue();
 
 
-    /* 入队 */
-    bool enQueue(const T& data);
-    bool enQueue(T&& data);
-    /* 阻塞入队 */
-    void enQueueBlock(const T& data);
-    /* 出队 */
-    bool deQueue(T& data);
-    /* 阻塞出队 */
-    T deQueueBlock();
-
-    /* 获取队列中第一个值(下一个出队的元素),但是不出队,非阻塞 */
-    bool front(T& t);
-    T& frontBlock();
-    /* 获取队列中即将入队的位置(这个函数用于存储指针的环形队列,获取内存地址) */
-    T& backBlock();
-
+    /* 入队,默认是阻塞入队 */
+    void push(const T& value);
+    void push(T&& value);
+    bool push_NoBlock(const T& value);
+    bool push_NoBlock(T&& value);
+
+    /* 出队,删除队列的首个元素
+     * 注意,如果存储的是指针,需要手动释放该指针指向的内存区域,不然会造成内存泄漏 */
+    void pop();
+
+    /* 获取队列中第一个值),但是不出队
+     * 阻塞的方式获取,如果队列为空,会一直阻塞住,直到获取到数据为止 */
+    T front();
+    /* 非阻塞的方式获取,队列为空返回false */
+    bool front_NoBlock(T& t);
+
+    /* 获取对立第一个数据,获取完立刻出队
+     * 如果队列为空,会阻塞住,直到有数据为止 */
+    T&& front_pop();
+    // T&& front_pop_rvalue();
+    bool front_pop_NoBlock(T& t);
+    
     /* 获取队列大小,队列中有效值的大小 */
     /* 获取队列大小,队列中有效值的大小 */
     long getQueueSize();
     long getQueueSize();
     /* 获取队列容量 */
     /* 获取队列容量 */
@@ -69,15 +77,18 @@ public:
     bool isEmpty();
     bool isEmpty();
     /* 判断队列是否已满 */
     /* 判断队列是否已满 */
     bool isFull();
     bool isFull();
+    /* 退出所有可能的阻塞函数 */
+    void exit();
 
 
 private:
 private:
+    bool m_isExit = false;                  /* 是否退出,这个标识位是为了退出阻塞住的函数 */
     std::mutex m_mutex;                     /* 互斥锁 */
     std::mutex m_mutex;                     /* 互斥锁 */
     T* m_queue = nullptr;                   /* 队列 */
     T* m_queue = nullptr;                   /* 队列 */
     long m_capacity = 0;     /* 队列容量 */
     long m_capacity = 0;     /* 队列容量 */
     long m_front = 0;        /* 队头 */
     long m_front = 0;        /* 队头 */
     long m_rear = 0;         /* 队尾 */
     long m_rear = 0;         /* 队尾 */
-    std::condition_variable m_cond_NoFull;      /* 非条件变量 */
-    std::condition_variable m_cond_NoEmpty;     /* 非条件变量 */
+    std::condition_variable m_cond_NoFull;      /* 非条件变量 */
+    std::condition_variable m_cond_NoEmpty;     /* 非条件变量 */
 };
 };
 
 
 
 
@@ -149,167 +160,236 @@ void RingQueue<T>::clearQueue()
 }
 }
 
 
 
 
-/* 入队 */
+/*************** 入队 *******************/
 template<typename T>
 template<typename T>
-bool RingQueue<T>::enQueue(const T& data)
+void RingQueue<T>::push(const T& value)
 {
 {
-    m_mutex.lock();
-    /* 先检查队列是否还有剩余空间 */
-    if(isFull())
     {
     {
-        return false;
+        std::unique_lock<std::mutex> lock(m_mutex);
+        m_cond_NoFull.wait(lock, [this](){
+            return (!isFull() || m_isExit);
+        });
+        if(m_isExit)
+        {
+            return;
+        }
+
+        if(m_rear == -1)
+        {
+            m_front = 0;
+            m_rear = 0;
+        }
+
+        m_queue[m_rear] = value;
+        m_rear = (m_rear + 1) % m_capacity;
     }
     }
-    else 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();
     m_cond_NoEmpty.notify_all();
-    return true;
 }
 }
 
 
-/* 入队,传入右值 */
 template<typename T>
 template<typename T>
-bool RingQueue<T>::enQueue(T&& data)
+void RingQueue<T>::push(T&& value)
 {
 {
-    m_mutex.lock();
-    /* 先检查队列是否还有剩余空间 */
-    if(isFull())
-    {
-        return false;
-    }
-    else if(m_rear == -1)
     {
     {
-        m_front = 0;
-        m_rear = 0;
+        std::unique_lock<std::mutex> lock(m_mutex);
+        m_cond_NoFull.wait(lock, [this](){
+            return (!isFull() || m_isExit);
+        });
+        if(m_isExit)
+        {
+            return;
+        }
+
+        if(m_rear == -1)
+        {
+            m_front = 0;
+            m_rear = 0;
+        }
+
+        m_queue[m_rear] = std::move(value);
+        m_rear = (m_rear + 1) % m_capacity;
     }
     }
 
 
-    m_queue[m_rear] = std::move(data);
-    m_rear = (m_rear + 1) % m_capacity;
-
-    m_mutex.unlock();
     m_cond_NoEmpty.notify_all();
     m_cond_NoEmpty.notify_all();
-    return true;
 }
 }
 
 
-/* 阻塞入队 */
-template<typename T>
-void RingQueue<T>::enQueueBlock(const T& data)
+/**
+ * @brief 非阻塞的方式入队,如果队列已满,直接返回
+ * 
+ */
+ template<typename T>
+bool RingQueue<T>::push_NoBlock(const T& value)
 {
 {
-    std::unique_lock<std::mutex> lock(m_mutex);
-    m_cond_NoFull.wait(lock, [this](){
-        return !isFull();
-    });
-
-    if(m_rear == -1)
     {
     {
-        m_front = 0;
-        m_rear = 0;
+        // std::unique_lock<std::mutex> lock(m_mutex, std::defer_lock);
+        // if(!lock.try_lock())
+        // {
+        //     return false;
+        // }
+        std::lock_guard<std::mutex> lock(m_mutex);
+        /* 先检查队列是否还有剩余空间 */
+        if(isFull())
+        {
+            return false;
+        }
+        else if(m_rear == -1)
+        {
+            m_front = 0;
+            m_rear = 0;
+        }
+
+        m_queue[m_rear] = value;
+        m_rear = (m_rear + 1) % m_capacity;
     }
     }
-
-    m_queue[m_rear] = data;
-    m_rear = (m_rear + 1) % m_capacity;
-    m_mutex.unlock();
     m_cond_NoEmpty.notify_all();
     m_cond_NoEmpty.notify_all();
+    return true;
 }
 }
 
 
-/* 出队 */
 template<typename T>
 template<typename T>
-bool RingQueue<T>::deQueue(T& data)
+bool RingQueue<T>::push_NoBlock(T&& value)
 {
 {
-    m_mutex.lock();
-    if(isEmpty())
     {
     {
-        return false;
+        // std::unique_lock<std::mutex> lock(m_mutex, std::defer_lock);
+        // if(!lock.try_lock())
+        // {
+        //     return false;
+        // }
+        std::lock_guard<std::mutex> lock(m_mutex);
+        /* 先检查队列是否还有剩余空间 */
+        if(isFull())
+        {
+            return false;
+        }
+        else if(m_rear == -1)
+        {
+            m_front = 0;
+            m_rear = 0;
+        }
+
+        m_queue[m_rear] = std::move(value);
+        m_rear = (m_rear + 1) % m_capacity;
     }
     }
-    data = std::move(m_queue[m_front]);
+    m_cond_NoEmpty.notify_all();
+    return true;
+}
+
 
 
-    /* 判断队列是否为空了 */
-    m_front = (m_front + 1) % m_capacity;
-    if(m_front == m_rear)
+/**
+ * @brief 出队,删除队列的首个元素
+ *        注意,如果存储的是指针,需要手动释放该指针指向的内存区域,不然会造成内存泄漏
+ * 
+ * @tparam T 
+ */
+template<typename T>
+void RingQueue<T>::pop()
+{
     {
     {
-        m_front = -1;
-        m_rear = -1;
+        std::unique_lock<std::mutex> lock(m_mutex);
+        if(isEmpty())
+        {
+            return;
+        }
+        m_front = (m_front + 1) % m_capacity;
+        if(m_front == m_rear)
+        {
+            m_front = -1;
+            m_rear = -1;
+        }
     }
     }
-
-    m_mutex.unlock();
     m_cond_NoFull.notify_all();
     m_cond_NoFull.notify_all();
-    return true;
 }
 }
 
 
-/* 出队 */
+
+/* 获取队列中第一个值,但是不出队
+ * 阻塞的方式获取,如果队列为空,会一直阻塞住,直到获取到数据为止 */
 template<typename T>
 template<typename T>
-T RingQueue<T>::deQueueBlock()
+T RingQueue<T>::front()
 {
 {
-    std::unique_lock<std::mutex> lock(m_mutex);
-    m_cond_NoEmpty.wait(lock, [this](){
-        return !isEmpty();
-    });
-
-    long tmp = m_front;
-    m_front = (m_front + 1) % m_capacity;
-    if(m_front == m_rear)
+    T retValue;
     {
     {
-        m_front = -1;
-        m_rear = -1;
+        std::unique_lock<std::mutex> lock(m_mutex);
+        m_cond_NoEmpty.wait(lock, [this](){
+            return (!isEmpty() || m_isExit);
+        });
+        if(m_isExit)
+        {
+            return retValue;
+        }
+        retValue = m_queue[m_front];
     }
     }
-    auto ret = m_queue[tmp];
-    m_cond_NoFull.notify_all();
-    return ret;
+    return retValue;
 }
 }
 
 
-/* 获取队列中第一个值(下一个出队的元素),但是不出队,非阻塞 */
+
+/* 获取队列中第一个值,但是不出队,非阻塞的方式获取 */
 template<typename T>
 template<typename T>
-bool RingQueue<T>::front(T& t)
+bool RingQueue<T>::front_NoBlock(T& t)
 {
 {
-    std::lock_guard<std::mutex> lock(m_mutex);
-    if(isEmpty())
     {
     {
-        return false;
+        std::unique_lock<std::mutex> lock(m_mutex);
+        if(isEmpty())
+        {
+            return false;
+        }
+        t = m_queue[m_front];
     }
     }
-    t = m_queue[m_front];
     return true;
     return true;
 }
 }
 
 
-/* 阻塞获取队列中第一个数据,但是不出队 */
+/* 获取对立第一个数据,获取完立刻出队
+ * 如果队列为空,会阻塞住,直到有数据为止 */
 template<typename T>
 template<typename T>
-T& RingQueue<T>::frontBlock()
+T&& RingQueue<T>::front_pop()
 {
 {
-    std::lock_guard<std::mutex> lock(m_mutex);
-    m_cond_NoEmpty.wait(lock, [this](){
-        return !isEmpty();
-    });
-    return m_queue[m_front];
+    T ret;
+    {
+        std::unique_lock<std::mutex> lock(m_mutex);
+        m_cond_NoEmpty.wait(lock, [this](){
+            return (!isEmpty() || m_isExit);
+        });
+        if(m_isExit)
+        {
+            return std::move(ret);
+        }
+        ret = std::move(m_queue[m_front]);
+        m_front = (m_front + 1) % m_capacity;
+        if(m_front == m_rear)
+        {
+            m_front = -1;
+            m_rear = -1;
+        }
+    }
+    m_cond_NoFull.notify_all();
+    return std::move(ret);
 }
 }
 
 
-/**
- * @brief 获取队列中即将入队的位置(这个函数用于存储指针的环形队列,获取内存地址)
- *        这个函数不一定内存安全,谨慎使用
- * 
- * @tparam T 
- * @return T& 
- */
+
 template<typename T>
 template<typename T>
-T& RingQueue<T>::backBlock()
+bool RingQueue<T>::front_pop_NoBlock(T& t)
 {
 {
-    std::lock_guard<std::mutex> lock(m_mutex);
-    m_cond_NoFull.wait(lock, [this](){
-        return !isFull();
-    });
-
-    return m_queue[m_rear];
+    {
+        std::unique_lock<std::mutex> lock(m_mutex);
+        if(isEmpty())
+        {
+            return false;
+        }
+        t = std::move(m_queue[m_front]);
+        m_front = (m_front + 1) % m_capacity;
+        if(m_front == m_rear)
+        {
+            m_front = -1;
+            m_rear = -1;
+        }
+    }
+    m_cond_NoFull.notify_all();
+    return true;
 }
 }
 
 
+
 /* 获取队列中有效值的大小 */
 /* 获取队列中有效值的大小 */
 template<typename T>
 template<typename T>
 long RingQueue<T>::getQueueSize()
 long RingQueue<T>::getQueueSize()
 {
 {
+    std::lock_guard<std::mutex> lock(m_mutex);
     if(m_rear == -1)
     if(m_rear == -1)
     {
     {
         return 0;
         return 0;
@@ -330,6 +410,7 @@ long RingQueue<T>::getQueueSize()
 template<typename T>
 template<typename T>
 long RingQueue<T>::getQueueCapacity()
 long RingQueue<T>::getQueueCapacity()
 {
 {
+    std::lock_guard<std::mutex> lock(m_mutex);
     return m_capacity;
     return m_capacity;
 }
 }
 
 
@@ -372,7 +453,14 @@ bool RingQueue<T>::isFull()
     return false;
     return false;
 }
 }
 
 
-
+/* 退出所有可能的阻塞函数 */
+template<typename T>
+void RingQueue<T>::exit()
+{
+    m_isExit = true;
+    m_cond_NoFull.notify_all();
+    m_cond_NoEmpty.notify_all();
+}