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

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值