线程安全的链表

template<typename T>
class ThreadsafeList
{
    struct Node
    {
        std::mutex m;
        std::shared_ptr<T> data;
        std::unique_ptr<Node> next;

        Node():
            next(nullptr)
        {}

        Node(T const& value):
            data(std::make_shared<T>(value))
        {}
    };

    Node head;

public:
    ThreadsafeList() = default;
    ThreadsafeList(const ThreadsafeList&) = delete;
    ThreadsafeList& operator=(const ThreadsafeList&) = delete;
    ~ThreadsafeList()
    {
        removeIf([](T const&){return true;});
    }

    void pushFront(T const& value)
    {
        auto newNode = std::make_unique<Node>(value);
        std::unique_lock<std::mutex> lock(head.m);
        newNode->next = std::move(head.next);
        head.next = std::move(newNode);
    }

    template<typename Function>
    void forEach(Function f)
    {
        Node* current = &head;
        std::unique_lock<std::mutex> lock(head.m);
        while(auto const next = current->next.get ()){
            std::unique_lock<std::mutex> nextLock(next->m);
            lock.unlock ();
            f(*next->data);
            current = next;
            lock = std::move(nextLock);
        }
    }

    template<typename Predicate>
    std::shared_ptr<T> findFirstIf(Predicate p)
    {
        Node* current = &head;
        std::unique_lock<std::mutex> lock(head.m);
        while(auto const next = current->next.get ()){
            std::unique_lock<std::mutex> nextLock(next->m);
            lock.unlock ();
            if (p(*next->data)){
                return next->data;
            }
            current = next;
            lock = std::move(nextLock);
        }
        return std::shared_ptr<T>();
    }

    template<typename Predicate>
    void removeIf(Predicate p)
    {
        Node* current = &head;
        std::unique_lock<std::mutex> lock(head.m);
        while(auto const next = current->next.get ()){
            std::unique_lock<std::mutex> nextLock(next->m);
            if (p(*next->data)){
                auto oldNext = std::move(current->next);
                current->next = std::move(next->next);
                nextLock.unlock ();
            }
            else{
                lock.unlock ();
                current = next;
                lock = std::move(nextLock);
            }
        }
    }
};

 

posted @ 2015-09-29 09:33  wu_overflow  阅读(1130)  评论(0编辑  收藏  举报