zoukankan      html  css  js  c++  java
  • 细粒度锁的极简单线程安全队列

    template<typename T>
    class ThreadsafeQueue
    {
    private:
        struct Node
        {
            std::shared_ptr<T>       data;
            std::unique_ptr<T>       next;
        };
    
        std::unique_ptr<Node>        head;
        Node*                        tail;
        mutable std::mutex           headMutex;
        mutable std::mutex           tailMutex;
        std::condition_variable      dataCond;
    
        Node* getTail () const
        {
            std::lock_guard<std::mutex> lock(tailMutex);
            return tail;
        }
    
        std::unique_lock<std::mutex> waitForData();
    
        std::unique_ptr<Node> popHead ()
        {
            std::lock_guard<std::mutex> lock(headMutex);
            auto oldHead = std::move(head);
            head = std::move(oldHead->next);
            return oldHead;
        }
    
        std::unique_ptr<Node> waitPopHead ()
        {
            std::unique_lock<std::mutex> lock(waitForData ());
            return popHead ();
        }
    
        std::unique_ptr<Node> waitPopHead (T& popedValue)
        {
            std::unique_lock<std::mutex> lock(waitForData ());
            popedValue = std::move(*head->data);
            return popHead ();
        }
    
        std::unique_ptr<Node> tryPopHead ()
        {
            std::lock_guard<std::mutex> lock(headMutex);
            if (head.get () == getTail ()){
                return std::unique_ptr<Node>();
            }
            return popHead ();
        }
    
        std::unique_ptr<Node> tryPopHead (T& popedValue)
        {
            std::lock_guard<std::mutex> lock(headMutex);
            if (head.get () == getTail ()){
                return std::unique_ptr<Node>();
            }
            popedValue = std::move(*head->data);
            return popHead ();
        }
    
    public:
        ThreadsafeQueue():
            head(std::make_shared<T>()), tail(head.get ())
        {}
    
        ThreadsafeQueue(const ThreadsafeQueue&)            = delete;
        ThreadsafeQueue& operator=(const ThreadsafeQueue&) = delete;
    
        std::shared_ptr<T>           tryPop();
        bool                         tryPop(T&);
        std::shared_ptr<T>           waitAndPop();
        void                         waitAndPop(T& value);
        void                         push(T newValue);
        bool                         empty();
    };
    
    template<typename T>
    void ThreadsafeQueue<T>::push (T newValue)
    {
        auto const newData = std::make_shared<T>(std::move(newValue));
        auto       newNext = std::make_unique<Node>();
        auto       newTail = newNext.get();
        std::lock_guard<std::mutex> lock(tailMutex);
        tail->next = std::move(newNext);
        tail->data = newData;
        tail = newTail;
        dataCond.notify_one ();
    }
    
    template<typename T>
    inline std::unique_lock<std::mutex> ThreadsafeQueue<T>::waitForData ()
    {
        std::unique_lock<std::mutex> lock(headMutex);
        dataCond.wait(lock, [&]{return head != getTail ();});
        return std::move(lock);
    }
    
    template<typename T>
    inline bool ThreadsafeQueue<T>::empty ()
    {
        std::lock_guard<std::mutex> lock(headMutex);
        return (head.get () == getTail ());
    }
    
    template<typename T>
    inline std::shared_ptr<T> ThreadsafeQueue<T>::waitAndPop ()
    {
        auto const oldHead = waitPopHead ();
        return oldHead->data;
    }
    
     template<typename T>
    inline void ThreadsafeQueue<T>::waitAndPop (T& popedValue)
    {
        waitPopHead (popedValue);
    }
    
    template<typename T>
    inline std::shared_ptr<T> ThreadsafeQueue<T>::tryPop ()
    {
        auto const oldHead = tryPopHead();
        return oldHead? oldHead->data : std::shared_ptr<T>();
    }
    
    template<typename T>
    inline bool ThreadsafeQueue<T>::tryPop (T& popedValue)
    {
        auto const oldHead = tryPopHead (popedValue);
        return oldHead;
    }
     
  • 相关阅读:
    SpringBoot整合Flyway(数据库版本迁移工具)
    Java并发编程实战 05等待-通知机制和活跃性问题
    Java并发编程实战 04死锁了怎么办?
    Java并发编程实战 03互斥锁 解决原子性问题
    Java并发编程实战 02Java如何解决可见性和有序性问题
    Flutter学习笔记(40)--Timer实现短信验证码获取60s倒计时
    Flutter学习笔记(39)--BottomNavigationBar底部item超过3个只显示icon,不显示title
    Flutter学习笔记(38)--自定义控件之组合控件
    Flutter学习笔记(36)--常用内置动画
    Flutter学习笔记(37)--动画曲线Curves 效果
  • 原文地址:https://www.cnblogs.com/wuOverflow/p/4840039.html
Copyright © 2011-2022 走看看