Template<typename t>classthreadsafequeue{Private: structNode {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); returntail; } 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); returnOldhead; } std::unique_ptr<Node>Waitpophead () {Std::unique_lock<std::mutex>Lock(Waitfordata ()); returnPophead (); } std::unique_ptr<Node> Waitpophead (t&popedvalue) {Std::unique_lock<std::mutex>Lock(Waitfordata ()); Popedvalue= Std::move (*head->data); returnPophead (); } std::unique_ptr<Node>Trypophead () {Std::lock_guard<std::mutex>Lock(Headmutex); if(head.Get() ==GetTail ()) { returnStd::unique_ptr<node>(); } returnPophead (); } std::unique_ptr<Node> Trypophead (t&popedvalue) {Std::lock_guard<std::mutex>Lock(Headmutex); if(head.Get() ==GetTail ()) { returnStd::unique_ptr<node>(); } popedvalue= Std::move (*head->data); returnPophead (); } Public: Threadsafequeue (): Head (std::make_shared<T> ()), tail (head.Get()) {} threadsafequeue (Constthreadsafequeue&) =Delete; Threadsafequeue&operator=(Constthreadsafequeue&) =Delete; Std::shared_ptr<T>Trypop (); BOOLTrypop (t&); Std::shared_ptr<T>Waitandpop (); voidWaitandpop (t&value); voidpush (T newvalue); BOOLempty ();}; Template<typename t>voidThreadsafequeue<t>::p ush (T newvalue) {AutoConstNewData = 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, [&]{returnHead! =gettail ();}); returnStd::move (Lock);} Template<typename t>inlineBOOLThreadsafequeue<t>:: Empty () {Std::lock_guard<std::mutex>Lock(Headmutex); return(head.Get() ==GetTail ());} Template<typename t>inline Std::shared_ptr<T> threadsafequeue<t>:: Waitandpop () {AutoConstOldhead =Waitpophead (); returnOldhead->data;} Template<typename t>inlinevoidThreadsafequeue<t>::waitandpop (t&popedvalue) {Waitpophead (popedvalue);} Template<typename t>inline Std::shared_ptr<T> threadsafequeue<t>:: Trypop () {AutoConstOldhead =Trypophead (); returnOldhead? Oldhead->data:std::shared_ptr<t>();} Template<typename t>inlineBOOLThreadsafequeue<t>::trypop (t&popedvalue) {AutoConstOldhead =Trypophead (Popedvalue); returnOldhead;}
Very simple thread-safe queue with fine-grained locks