c++簡單線程安全隊列的實現

說明:主要是記錄自己的練習,不保證代碼正確,請勿參考。

 

#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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章