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;
    }
     
  • 相关阅读:
    HD2058The sum problem
    采用循环链表结构求解约瑟夫问题
    java线性表学习笔记(二)
    java线性表学习笔记(一)
    HD1004Let the Balloon Rise
    HD1005Number Sequence
    用c++库函数轻松解决回文问题
    accelerated C++ 中查找url(学习笔记)
    C++ 之关联容器 map
    pytorch 迁移学习[摘自官网]
  • 原文地址:https://www.cnblogs.com/wuOverflow/p/4840039.html
Copyright © 2011-2022 走看看