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; }
时间: 2024-10-15 06:02:46