细粒度锁的极简单线程安全队列

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;
}

 

 
posted @ 2015-09-26 09:18  wu_overflow  阅读(639)  评论(0编辑  收藏  举报