說明:主要是記錄自己的練習,不保證代碼正確,請勿參考。
#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