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;
    }
     
  • 相关阅读:
    从gettext来看linux下程序的internationalization
    C++ Convert Operator和其他Operator的应用场景比较
    申明一个函数指针,并且该函数的返回值也是一个函数指针 示例代码
    XML操作大全
    如何让页面延迟显示?
    Ajax实现不刷屏的前提下实现页面定时刷新
    我喜欢的笑话 呵呵
    Atlas UpdatePanel使用技巧以及常见问题
    asp.net 弹出窗体
    C# asp.net操作文件
  • 原文地址:https://www.cnblogs.com/wuOverflow/p/4840039.html
Copyright © 2011-2022 走看看