说明:主要是记录自己的练习,不保证代码正确,请勿参考。
#ifndef THREADSAFEQUEUE_H
#define THREADSAFEQUEUE_H
#include<memory>
#include<mutex>
#include<condition_variable>
using namespace std;
namespace com{
namespace example{
namespace testone{
namespace thread{
namespace data_structures{
template<typename T>
class ThreadSafeQueue
{
private:
struct Node{
std::shared_ptr<T> data;
std::unique_ptr<Node> next;
Node(T t){
data = std::make_shared<T>(std::move(t));
}
Node(){}
};
public:
ThreadSafeQueue(){
//不要将裸指针直接赋值给智能指针
this->head = std::move(std::unique_ptr<Node>(new Node()));
this->tail = this->head.get();
}
virtual ~ThreadSafeQueue(){
}
ThreadSafeQueue(const ThreadSafeQueue& q) = delete;
ThreadSafeQueue& operator=(const ThreadSafeQueue& q) = delete;
void push(T t){
std::shared_ptr<T> new_data = std::make_shared<T>(std::move(t));
//新建尾部结点, 不要将裸指针直接赋值给智能指针
std::unique_ptr<Node> new_node = std::move(std::unique_ptr<Node>(new Node()));
Node* new_tail = new_node.get();
std::unique_lock<std::mutex> myLock(this->tailMutex);//只有修改this->tail的地方需要加尾部锁
//给当前的尾部结点赋值
this->tail->data = new_data;
this->tail->next = std::move(new_node);
//修改尾部结点
this->tail = new_tail;
myLock.unlock();
//先释放尾部锁,然后通知条件变量上等待的线程觉醒
this->mCondition.notify_one();
}
std::shared_ptr<T> try_pop(){
//所有访问到this->head的地方都需要加头部锁
std::lock_guard<std::mutex>(this->headMutex);
//判断队列中是否有内容
if(this->head.get() == this->getTail()){ //getTail()里面加了尾部锁
return std::shared_ptr<T>();
}
//获取当前头部的值
std::shared_ptr<T> ret_value = std::move(this->head->data);
//更新head指向的位置
std::unique_ptr<Node> old_head = std::move(this->head);
this->head = std::move(old_head->next);
return ret_value;
}
std::shared_ptr<T> wait_and_pop(){
//this->mCondition.wait(this->headMutex, &ThreadSafeQueue::isNotEmpty);
std::unique_lock<std::mutex> lk(this->headMutex);
while(this->head.get() == this->getTail()){
this->mCondition.wait(lk);
}
//获取头部元素
std::shared_ptr<T> ret_value = std::move(this->head->data);
//移除头部元素
std::unique_ptr<Node> old_head = std::move(this->head);
this->head = std::move(old_head->next);
return ret_value;
}
Node* getTail(){
std::lock_guard<std::mutex>(this->tailMutex);
return this->tail;
}
protected:
private:
bool isNotEmpty(){
std::lock_guard<std::mutex> lk(this->headMutex);
return this->head.get() != getTail();
}
private:
std::unique_ptr<Node> head;//头部的指针
Node* tail;//尾部的指针
std::mutex headMutex;
std::mutex tailMutex;
std::condition_variable mCondition;
};
}
}
}
}
}
#endif // THREADSAFEQUEUE_H