|
@@ -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();
|
|
|
|
+}
|
|
|
|
|
|
|
|
|
|
|
|
|