소스 검색

V0.11.3
1、修改了环形队列相关内容

Apple 4 일 전
부모
커밋
50c95ce99a
1개의 변경된 파일158개의 추가작업 그리고 85개의 파일을 삭제
  1. 158 85
      module/RingQueue/RingQueue.hpp

+ 158 - 85
module/RingQueue/RingQueue.hpp

@@ -5,7 +5,7 @@
 #include <utility>
 #include <mutex>
 #include <condition_variable>
-// #include <atomic>
+#include <atomic>
 
 /**
  * @brief 这里采用零公摊的方式,设置多大的空间,就有多大的空间可以使用
@@ -32,10 +32,13 @@
  * @tparam T 模版类型
  */
 
+#define _DefaultValue (m_isUseDefaultValue.load() ? m_defaultValue : T{})
+
 template<typename T>
 class RingQueue
-{    
-
+{
+    RingQueue(const RingQueue<T>& queue) = delete;
+    RingQueue<T> operator=(const RingQueue<T>& queue) = delete;
 public:
     RingQueue();
     RingQueue(long size);
@@ -45,8 +48,8 @@ public:
     /* 入队,默认是阻塞入队 */
     void push(const T& value);
     void push(T&& value);
-    bool push_NoBlock(const T& value);
-    bool push_NoBlock(T&& value);
+    bool push_noBlock(const T& value);
+    bool push_noBlock(T&& value);
 
     /* 出队,删除队列的首个元素
      * 注意,如果存储的是指针,需要手动释放该指针指向的内存区域,不然会造成内存泄漏 */
@@ -56,17 +59,21 @@ public:
      * 阻塞的方式获取,如果队列为空,会一直阻塞住,直到获取到数据为止 */
     T front();
     /* 非阻塞的方式获取,队列为空返回false */
-    bool front_NoBlock(T& t);
+    bool front_noBlock(T& t);
     /* 非阻塞方式获取第一个值,如果对列为空,则会返回设置的默认值 */
-    T front_NoBlock();
+    T front_noBlock();
 
     /* 获取对立第一个数据,获取完立刻出队
-     * 如果队列为空,会阻塞住,直到有数据为止 */
+     * 如果队列为空,会阻塞住,直到有数据为止
+     * 如果删除了拷贝构造函数,使用会报错 */
     T front_pop();
     /* 非阻塞方式获取第一个值,并出队 */
-    bool front_pop_NoBlock(T& t);
+    bool front_pop_noBlock(T& t);
     /* 非阻塞方式获取第一个值,并出队,如果队列为空,会返回设置的默认值 */
-    T front_pop_NoBlock();
+    T front_pop_noBlock();
+    /* 通过移动语义获取数据,获取完成后队列中的数据只是个空壳了,因此直接就出队了 */
+    bool front_pop_move(T& t);
+    bool front_pop_move_noBlock(T& t);
     
     /* 设置队列大小 */
     void setQueueCapacity(long size);
@@ -86,13 +93,20 @@ public:
     void exit();
 
 private:
-    bool m_isExit = false;                  /* 是否退出,这个标识位是为了退出阻塞住的函数 */
+    /* 判断是否空 */
+    inline bool _isEmpty();
+    /* 判断是否满 */
+    inline bool _isFull();
+
+private:
+    std::atomic_bool m_isExit = false;      /* 是否退出,这个标识位是为了退出阻塞住的函数 */
     std::mutex m_mutex;                     /* 互斥锁 */
     T m_defaultValue;                       /* 默认值 */
+    std::atomic_bool m_isUseDefaultValue = false; /* 是否使用默认值 */
     T* m_queue = nullptr;                   /* 队列 */
-    long m_capacity = 0;                    /* 队列容量 */
-    long m_front = 0;                       /* 队头 */
-    long m_rear = 0;                        /* 队尾 */
+    long m_capacity = 0;                        /* 队列容量 */
+    long m_front = -1;                          /* 队头 */
+    long m_rear = -1;                           /* 队尾 */
     std::condition_variable m_cond_NoFull;      /* 非满条件变量 */
     std::condition_variable m_cond_NoEmpty;     /* 非空条件变量 */
 };
@@ -104,31 +118,30 @@ private:
 
 /* 这个构造函数需要调用 setQueueSize 设置环形队列的大小 */
 template<typename T>
-RingQueue<T>::RingQueue() : m_capacity(0) , m_front(-1), m_rear(-1)
+RingQueue<T>::RingQueue() 
 {
     
 }
 
 template<typename T>
-RingQueue<T>::RingQueue(long capacicy) : m_capacity(capacicy)
+RingQueue<T>::RingQueue(long capacity) 
 {
-    m_front = -1;
-    m_rear = -1;
-    m_queue = new T[m_capacity];
+    m_capacity = capacity;
+    m_queue = new T[m_capacity] {};
 }
 
 /* 添加默认值 */
 template<typename T>
-RingQueue<T>::RingQueue(long size, T defaultValue)
+RingQueue<T>::RingQueue(long capacity, T defaultValue)
 {
-    m_front = -1;
-    m_rear = -1;
-    m_queue = new T[m_capacity];
+    m_capacity = capacity;
+    m_queue = new T[m_capacity] {};
     for(long i = 0; i < m_capacity; i++)
     {
         m_queue[i] = defaultValue;
     }
     m_defaultValue = defaultValue;
+    m_isUseDefaultValue.store(true); // 设置使用默认值
 }
 
 template<typename T>
@@ -146,7 +159,7 @@ RingQueue<T>::~RingQueue()
 template<typename T>
 void RingQueue<T>::clearQueue()
 {
-    m_mutex.lock();
+    std::lock_guard<std::mutex> lock(m_mutex);
     if(m_queue != nullptr)
     {
         delete[] m_queue;
@@ -154,7 +167,6 @@ void RingQueue<T>::clearQueue()
     }
     m_front = -1;
     m_rear = -1;
-    m_mutex.unlock();
 }
 
 
@@ -163,9 +175,9 @@ template<typename T>
 void RingQueue<T>::push(const T& value)
 {
     {
-        std::unique_lock<std::mutex> lock(m_mutex);
-        m_cond_NoFull.wait(lock, [this](){
-            return (!isFull() || m_isExit);
+        std::unique_lock<std::mutex> _lock(m_mutex);
+        m_cond_NoFull.wait(_lock, [this]() {
+            return (!_isFull() || m_isExit);
         });
         if(m_isExit)
         {
@@ -190,7 +202,7 @@ void RingQueue<T>::push(T&& value)
     {
         std::unique_lock<std::mutex> lock(m_mutex);
         m_cond_NoFull.wait(lock, [this](){
-            return (!isFull() || m_isExit);
+            return (!_isFull() || m_isExit);
         });
         if(m_isExit)
         {
@@ -215,7 +227,7 @@ void RingQueue<T>::push(T&& value)
  * 
  */
  template<typename T>
-bool RingQueue<T>::push_NoBlock(const T& value)
+bool RingQueue<T>::push_noBlock(const T& value)
 {
     {
         // std::unique_lock<std::mutex> lock(m_mutex, std::defer_lock);
@@ -225,7 +237,7 @@ bool RingQueue<T>::push_NoBlock(const T& value)
         // }
         std::lock_guard<std::mutex> lock(m_mutex);
         /* 先检查队列是否还有剩余空间 */
-        if(isFull())
+        if(_isFull())
         {
             return false;
         }
@@ -243,7 +255,7 @@ bool RingQueue<T>::push_NoBlock(const T& value)
 }
 
 template<typename T>
-bool RingQueue<T>::push_NoBlock(T&& value)
+bool RingQueue<T>::push_noBlock(T&& value)
 {
     {
         // std::unique_lock<std::mutex> lock(m_mutex, std::defer_lock);
@@ -253,7 +265,7 @@ bool RingQueue<T>::push_NoBlock(T&& value)
         // }
         std::lock_guard<std::mutex> lock(m_mutex);
         /* 先检查队列是否还有剩余空间 */
-        if(isFull())
+        if(_isFull())
         {
             return false;
         }
@@ -282,7 +294,7 @@ void RingQueue<T>::pop()
 {
     {
         std::unique_lock<std::mutex> lock(m_mutex);
-        if(isEmpty())
+        if(_isEmpty())
         {
             return;
         }
@@ -302,29 +314,27 @@ void RingQueue<T>::pop()
 template<typename T>
 T RingQueue<T>::front()
 {
-    T retValue;
+    
+    std::unique_lock<std::mutex> lock(m_mutex);
+    m_cond_NoEmpty.wait(lock, [this](){
+        return (!isEmpty() || m_isExit);
+    });
+    if(m_isExit)
     {
-        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];
+        return _DefaultValue;
     }
-    return retValue;
+    return m_queue[m_front];
+    
 }
 
 
 /* 获取队列中第一个值,但是不出队,非阻塞的方式获取 */
 template<typename T>
-bool RingQueue<T>::front_NoBlock(T& t)
+bool RingQueue<T>::front_noBlock(T& t)
 {
     {
         std::unique_lock<std::mutex> lock(m_mutex);
-        if(isEmpty())
+        if(_isEmpty())
         {
             return false;
         }
@@ -336,18 +346,14 @@ bool RingQueue<T>::front_NoBlock(T& t)
 
 /* 非阻塞方式获取第一个值,如果对列为空,则会返回设置的默认值 */
 template<typename T>
-T RingQueue<T>::front_NoBlock()
+T RingQueue<T>::front_noBlock()
 {
-    T ret;
+    std::unique_lock<std::mutex> lock(m_mutex);
+    if(_isEmpty())
     {
-        std::unique_lock<std::mutex> lock(m_mutex);
-        if(isEmpty())
-        {
-            return m_defaultValue;
-        }
-        ret = m_queue[m_front];
+        return _DefaultValue;
     }
-    return ret;
+    return m_queue[m_front];
 }
 
 /* 获取对立第一个数据,获取完立刻出队
@@ -355,36 +361,37 @@ T RingQueue<T>::front_NoBlock()
 template<typename T>
 T RingQueue<T>::front_pop()
 {
-    T ret = m_defaultValue;
+    // T ret = _DefaultValue;
     {
         std::unique_lock<std::mutex> lock(m_mutex);
         m_cond_NoEmpty.wait(lock, [this](){
-            return (!isEmpty() || m_isExit);
+            return (!_isEmpty() || m_isExit);
         });
         /* 是否退出 */
         if(m_isExit)
         {
-            return ret;
+            return _DefaultValue;
         }
-        ret = std::move(m_queue[m_front]);
+        /* 临时记录索引 */
+        long front = 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 m_queue[front];
     }
-    m_cond_NoFull.notify_all();
-    return ret;
 }
 
 /* 非阻塞方式获取第一个值,并出队 */
 template<typename T>
-bool RingQueue<T>::front_pop_NoBlock(T& t)
+bool RingQueue<T>::front_pop_noBlock(T& t)
 {
     {
         std::unique_lock<std::mutex> lock(m_mutex);
-        if(isEmpty())
+        if(_isEmpty())
         {
             return false;
         }
@@ -402,28 +409,79 @@ bool RingQueue<T>::front_pop_NoBlock(T& t)
 
 /* 非阻塞方式获取第一个值,并出队 */
 template<typename T>
-T RingQueue<T>::front_pop_NoBlock()
+T RingQueue<T>::front_pop_noBlock()
 {
-    T ret = m_defaultValue;
+    // T ret = _DefaultValue;
     {
         std::unique_lock<std::mutex> lock(m_mutex);
         // m_cond_NoEmpty.wait(lock, [this](){
-        //     return (!isEmpty() || m_isExit);
+        //     return (!_isEmpty() || m_isExit);
         // });
-        if(isEmpty())
+        if(_isEmpty())
         {
-            return ret;
+            return _DefaultValue;
         }
-        ret = std::move(m_queue[m_front]);
+        /* 临时记录索引 */
+        long front = 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 m_queue[front];
+    }
+}
+
+/* 通过移动语义获取数据,获取完成后队列中的数据只是个空壳了,因此直接就出队了 */
+template<typename T>
+bool RingQueue<T>::front_pop_move(T& t)
+{
+    std::unique_lock<std::mutex> lock(m_mutex);
+    m_cond_NoEmpty.wait(lock, [this]() {
+        return (!_isEmpty() || m_isExit);
+    });
+    /* 是否退出 */
+    if(m_isExit)
+    {
+        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>
+bool RingQueue<T>::front_pop_move_noBlock(T& t)
+{
+    std::unique_lock<std::mutex> lock(m_mutex);
+    // m_cond_NoEmpty.wait(lock, [this](){
+    //     return (!_isEmpty() || m_isExit);
+    // });
+    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 ret;
+
+    return true;
 }
 
 
@@ -456,6 +514,7 @@ template<typename T>
 void RingQueue<T>::setDefaultValue(T defaultValue)
 {
     m_defaultValue = defaultValue;
+    m_isUseDefaultValue.store(true); // 设置使用默认值
 }
 
 /* 获取队列中有效值的大小 */
@@ -497,12 +556,8 @@ long RingQueue<T>::QueueCapacity()
 template<typename T>
 bool RingQueue<T>::isEmpty()
 {
-    if((m_front == m_rear) && (m_front == -1))
-    {
-        return true;
-    }
-
-    return false;
+    std::lock_guard<std::mutex> lock(m_mutex);
+    return _isEmpty();
 }
 
 /**
@@ -516,14 +571,8 @@ bool RingQueue<T>::isEmpty()
 template<typename T>
 bool RingQueue<T>::isFull()
 {
-    /* 如果m_rear或者m_front不等于-1,说明此时里面有内容
-     * 同时m_front == m_rear,队列就满了 */
-    if(m_front == m_rear && m_rear != -1)
-    {
-        return true;
-    }
-    
-    return false;
+    std::lock_guard<std::mutex> lock(m_mutex);
+    return _isFull();
 }
 
 /* 退出所有可能的阻塞函数 */
@@ -535,6 +584,30 @@ void RingQueue<T>::exit()
     m_cond_NoEmpty.notify_all();
 }
 
+/* 判断是否空 */
+template<typename T>
+bool RingQueue<T>::_isEmpty()
+{
+    if((m_front == m_rear) && (m_front == -1))
+    {
+        return true;
+    }
+    return false;
+}
+
+/* 判断是否满 */
+template<typename T>
+inline bool RingQueue<T>::_isFull()
+{
+    /* 如果m_rear或者m_front不等于-1,说明此时里面有内容
+     * 同时m_front == m_rear,队列就满了 */
+    if(m_front == m_rear && m_rear != -1)
+    {
+        return true;
+    }
+    return false;
+}
+
 
 
 #endif /* RINGQUEUE_H */