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;
    }
     
  • 相关阅读:
    Happy Number
    [leedcode]Remove Linked List Elements
    [leedcode] Count Primes
    编写一个截取字符串的函数,输入为一个字符串和字节数,输出为按字节截取的字符串。 但是要保证汉字不被截半个,如“我ABC”4,应该截为“我AB”,输入“我ABC汉DEF”,6,应该输出为“我ABC”而不是“我ABC+汉的半个”。
    最短路(队列优化)
    两函数的交点
    最小生成树
    最小生成树
    线段树区间修改和查询和单点查询(线段树模板1)
    博弈论合集(博弈)
  • 原文地址:https://www.cnblogs.com/wuOverflow/p/4840039.html
Copyright © 2011-2022 走看看