{"id":7661,"date":"2023-07-01T09:21:14","date_gmt":"2023-07-01T09:21:14","guid":{"rendered":"https:\/\/www.modernescpp.com\/?p=7661"},"modified":"2023-08-23T17:02:40","modified_gmt":"2023-08-23T17:02:40","slug":"thread-safe-queue-two-serious-errors","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/thread-safe-queue-two-serious-errors\/","title":{"rendered":"Thread-Safe Queue &#8211; Two Serious Errors"},"content":{"rendered":"\n<p>In my last post &#8220;<a href=\"https:\/\/www.modernescpp.com\/index.php\/monitor-object\">Monitor Object<\/a>&#8221;&nbsp; I implemented a thread-safe queue. I made two serious errors. Sorry. Today, I will fix these issues.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1030\" height=\"520\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/07\/ConcurrencyPatterns-1030x520.png\" alt=\"\" class=\"wp-image-7662\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/07\/ConcurrencyPatterns-1030x520.png 1030w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/07\/ConcurrencyPatterns-300x151.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/07\/ConcurrencyPatterns-768x387.png 768w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/07\/ConcurrencyPatterns-705x356.png 705w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/07\/ConcurrencyPatterns.png 1245w\" sizes=\"auto, (max-width: 1030px) 100vw, 1030px\" \/><\/figure>\n\n\n\n<p>First, I want to show you again the erroneous implementation from my last post to understand the context.<\/p>\n\n\n\n<!-- HTML generated using hilite.me --><div style=\"background: #f0f3f3; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;\"><pre style=\"margin: 0; line-height: 125%\"><span style=\"color: #0099FF; font-style: italic\">\/\/ monitorObject.cpp<\/span>\n\n<span style=\"color: #009999\">#include &lt;condition_variable&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;functional&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;queue&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;iostream&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;mutex&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;random&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;thread&gt;<\/span>\n\n<span style=\"color: #006699; font-weight: bold\">class<\/span> <span style=\"color: #00AA88; font-weight: bold\">Monitor<\/span> {\n<span style=\"color: #9999FF\">public:<\/span>\n    <span style=\"color: #007788; font-weight: bold\">void<\/span> lock() <span style=\"color: #006699; font-weight: bold\">const<\/span> {\n        monitMutex.lock();\n    }\n\n    <span style=\"color: #007788; font-weight: bold\">void<\/span> unlock() <span style=\"color: #006699; font-weight: bold\">const<\/span> {\n        monitMutex.unlock();\n    }\n\n    <span style=\"color: #007788; font-weight: bold\">void<\/span> notify_one() <span style=\"color: #006699; font-weight: bold\">const<\/span> noexcept {\n        monitCond.notify_one();\n    }\n\n    <span style=\"color: #006699; font-weight: bold\">template<\/span> <span style=\"color: #555555\">&lt;<\/span><span style=\"color: #006699; font-weight: bold\">typename<\/span> Predicate<span style=\"color: #555555\">&gt;<\/span>\n    <span style=\"color: #007788; font-weight: bold\">void<\/span> wait(Predicate pred) <span style=\"color: #006699; font-weight: bold\">const<\/span> {                 <span style=\"color: #0099FF; font-style: italic\">\/\/ (10)<\/span>\n        std<span style=\"color: #555555\">::<\/span>unique_lock<span style=\"color: #555555\">&lt;<\/span>std<span style=\"color: #555555\">::<\/span>mutex<span style=\"color: #555555\">&gt;<\/span> monitLock(monitMutex);\n        monitCond.wait(monitLock, pred);\n    }\n    \n<span style=\"color: #9999FF\">private:<\/span>\n    <span style=\"color: #006699; font-weight: bold\">mutable<\/span> std<span style=\"color: #555555\">::<\/span>mutex monitMutex;\n    <span style=\"color: #006699; font-weight: bold\">mutable<\/span> std<span style=\"color: #555555\">::<\/span>condition_variable monitCond;\n};\n\n<span style=\"color: #006699; font-weight: bold\">template<\/span> <span style=\"color: #555555\">&lt;<\/span><span style=\"color: #006699; font-weight: bold\">typename<\/span> T<span style=\"color: #555555\">&gt;<\/span>                                  <span style=\"color: #0099FF; font-style: italic\">\/\/ (1)<\/span>\n<span style=\"color: #006699; font-weight: bold\">class<\/span> <span style=\"color: #00AA88; font-weight: bold\">ThreadSafeQueue<\/span><span style=\"color: #555555\">:<\/span> <span style=\"color: #006699; font-weight: bold\">public<\/span> Monitor {\n <span style=\"color: #9999FF\">public:<\/span>\n    <span style=\"color: #007788; font-weight: bold\">void<\/span> add(T val){ \n        lock();\n        myQueue.push(val);                             <span style=\"color: #0099FF; font-style: italic\">\/\/ (6)<\/span>\n        unlock();\n        notify_one();\n    }\n    \n    T get(){ \n        wait( [<span style=\"color: #006699; font-weight: bold\">this<\/span>] { <span style=\"color: #006699; font-weight: bold\">return<\/span> <span style=\"color: #555555\">!<\/span> myQueue.empty(); } );  <span style=\"color: #0099FF; font-style: italic\">\/\/ (2)<\/span>\n        lock();\n        <span style=\"color: #006699; font-weight: bold\">auto<\/span> val <span style=\"color: #555555\">=<\/span> myQueue.front();                    <span style=\"color: #0099FF; font-style: italic\">\/\/ (4)<\/span>\n        myQueue.pop();                                 <span style=\"color: #0099FF; font-style: italic\">\/\/ (5)<\/span>\n        unlock();\n        <span style=\"color: #006699; font-weight: bold\">return<\/span> val;\n    }\n\n<span style=\"color: #9999FF\">private:<\/span>\n    std<span style=\"color: #555555\">::<\/span>queue<span style=\"color: #555555\">&lt;<\/span>T<span style=\"color: #555555\">&gt;<\/span> myQueue;                            <span style=\"color: #0099FF; font-style: italic\">\/\/ (3)<\/span>\n};\n\n\n<span style=\"color: #006699; font-weight: bold\">class<\/span> <span style=\"color: #00AA88; font-weight: bold\">Dice<\/span> {\n<span style=\"color: #9999FF\">public:<\/span>\n    <span style=\"color: #007788; font-weight: bold\">int<\/span> <span style=\"color: #006699; font-weight: bold\">operator<\/span>()(){ <span style=\"color: #006699; font-weight: bold\">return<\/span> rand(); }\n<span style=\"color: #9999FF\">private:<\/span>\n    std<span style=\"color: #555555\">::<\/span>function<span style=\"color: #555555\">&lt;<\/span><span style=\"color: #007788; font-weight: bold\">int<\/span>()<span style=\"color: #555555\">&gt;<\/span> rand <span style=\"color: #555555\">=<\/span> std<span style=\"color: #555555\">::<\/span>bind(std<span style=\"color: #555555\">::<\/span>uniform_int_distribution<span style=\"color: #555555\">&lt;&gt;<\/span>(<span style=\"color: #FF6600\">1<\/span>, <span style=\"color: #FF6600\">6<\/span>), \n                                          std<span style=\"color: #555555\">::<\/span>default_random_engine());\n};\n\n\n<span style=\"color: #007788; font-weight: bold\">int<\/span> <span style=\"color: #CC00FF\">main<\/span>(){\n    \n    std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&#39;\\n&#39;<\/span>;\n    \n    constexpr <span style=\"color: #006699; font-weight: bold\">auto<\/span> NumberThreads <span style=\"color: #555555\">=<\/span> <span style=\"color: #FF6600\">100<\/span>;\n    \n    ThreadSafeQueue<span style=\"color: #555555\">&lt;<\/span><span style=\"color: #007788; font-weight: bold\">int<\/span><span style=\"color: #555555\">&gt;<\/span> safeQueue;                      <span style=\"color: #0099FF; font-style: italic\">\/\/ (7)<\/span>\n\n    <span style=\"color: #006699; font-weight: bold\">auto<\/span> addLambda <span style=\"color: #555555\">=<\/span> [<span style=\"color: #555555\">&amp;<\/span>safeQueue](<span style=\"color: #007788; font-weight: bold\">int<\/span> val){ safeQueue.add(val);          <span style=\"color: #0099FF; font-style: italic\">\/\/ (8)<\/span>\n                                            std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> val <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&quot; &quot;<\/span>\n                                            <span style=\"color: #555555\">&lt;&lt;<\/span> std<span style=\"color: #555555\">::<\/span>this_thread<span style=\"color: #555555\">::<\/span>get_id() <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&quot;; &quot;<\/span>; \n                                          }; \n    <span style=\"color: #006699; font-weight: bold\">auto<\/span> getLambda <span style=\"color: #555555\">=<\/span> [<span style=\"color: #555555\">&amp;<\/span>safeQueue]{ safeQueue.get(); };  <span style=\"color: #0099FF; font-style: italic\">\/\/ (9)<\/span>\n\n    std<span style=\"color: #555555\">::<\/span>vector<span style=\"color: #555555\">&lt;<\/span>std<span style=\"color: #555555\">::<\/span><span style=\"color: #006699; font-weight: bold\">thread<\/span><span style=\"color: #555555\">&gt;<\/span> addThreads(NumberThreads);\n    Dice dice;\n    <span style=\"color: #006699; font-weight: bold\">for<\/span> (<span style=\"color: #006699; font-weight: bold\">auto<\/span><span style=\"color: #555555\">&amp;<\/span> thr<span style=\"color: #555555\">:<\/span> addThreads) thr <span style=\"color: #555555\">=<\/span> std<span style=\"color: #555555\">::<\/span><span style=\"color: #006699; font-weight: bold\">thread<\/span>(addLambda, dice());\n\n    std<span style=\"color: #555555\">::<\/span>vector<span style=\"color: #555555\">&lt;<\/span>std<span style=\"color: #555555\">::<\/span><span style=\"color: #006699; font-weight: bold\">thread<\/span><span style=\"color: #555555\">&gt;<\/span> getThreads(NumberThreads);\n    <span style=\"color: #006699; font-weight: bold\">for<\/span> (<span style=\"color: #006699; font-weight: bold\">auto<\/span><span style=\"color: #555555\">&amp;<\/span> thr<span style=\"color: #555555\">:<\/span> getThreads) thr <span style=\"color: #555555\">=<\/span> std<span style=\"color: #555555\">::<\/span><span style=\"color: #006699; font-weight: bold\">thread<\/span>(getLambda);\n\n    <span style=\"color: #006699; font-weight: bold\">for<\/span> (<span style=\"color: #006699; font-weight: bold\">auto<\/span><span style=\"color: #555555\">&amp;<\/span> thr<span style=\"color: #555555\">:<\/span> addThreads) thr.join();\n    <span style=\"color: #006699; font-weight: bold\">for<\/span> (<span style=\"color: #006699; font-weight: bold\">auto<\/span><span style=\"color: #555555\">&amp;<\/span> thr<span style=\"color: #555555\">:<\/span> getThreads) thr.join();\n    \n    std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&quot;<\/span><span style=\"color: #CC3300; font-weight: bold\">\\n\\n<\/span><span style=\"color: #CC3300\">&quot;<\/span>;\n     \n}\n<\/pre><\/div>\n\n\n\n<p>The key idea of the example is that the Monitor Object is encapsulated in a class and can, therefore, be reused. The class&nbsp;<code>Monitor<\/code> uses a <code>std::mutex<\/code> as monitor lock and a <a href=\"https:\/\/www.modernescpp.com\/index.php\/tag\/condition-variable\"><code>std::condition_variable<\/code><\/a> as monitor condition. The class&nbsp;<code>Monitor<\/code> provides the minimal interface that a Monitor Object should support.<\/p>\n\n\n\n<p><code>ThreadSafeQueue<\/code> in line (1) extends&nbsp; <code>std::queue<\/code> in line (3) with a thread-safe interface. <code>ThreadSafeQueue<\/code> derives from the class <code>Monitor<\/code> and uses its member functions to support the synchronized member functions <code>add<\/code> and get. The member functions <code>add<\/code> and <code>get<\/code> use the monitor lock to protect the Monitor Object, particularly the non-thread-safe <code>myQueue<\/code>. <code>add<\/code> notifies the waiting thread when a new item was added to <code>myQueue<\/code>. This notification is thread-safe. The member function <code>get<\/code> (line (3)) deserves more attention. First, the <code>wait <\/code>member function of the underlying condition variable is called. This <code>wait<\/code> call needs an additional predicate to protect against spurious and lost wakeups (<a href=\"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-be-aware-of-the-traps-of-condition-variables\">C++ Core Guidelines: Be Aware of the Traps of Condition Variables<\/a>). The operations modifying&nbsp; <code>myQueue<\/code> (lines 4 and 5) must also be protected because they can interleave with the call <code>myQueue.push(val)<\/code> (line 6). The Monitor Object <code>safeQueue<\/code> line (7) uses the lambda functions in lines (8) and (9) to add or remove a number from the synchronized <code>safeQueue<\/code>. <code>ThreadSafeQueue<\/code> itself is a class template and can hold values from an arbitrary type. One hundred clients add 100 random numbers between 1 &#8211; 6 to&nbsp; <code>safeQueue<\/code> (line 7), while hundred clients remove these 100 numbers concurrently from the <code>safeQueue<\/code>. The output of the program shows the numbers and the thread ids.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"931\" height=\"589\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/07\/monitorObject-1.png\" alt=\"\" class=\"wp-image-7679\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/07\/monitorObject-1.png 931w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/07\/monitorObject-1-300x190.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/07\/monitorObject-1-768x486.png 768w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/07\/monitorObject-1-705x446.png 705w\" sizes=\"auto, (max-width: 931px) 100vw, 931px\" \/><\/figure>\n\n\n\n<p><div class=\"t3-wrapper magazine\"><div id=\"t3-mainbody\" class=\"container t3-mainbody\"><div class=\"row\"><div id=\"t3-content\" class=\"t3-content col-xs-12 col-md-6  col-md-push-3\"><div id=\"system\"><form action=\"\/index.php\/thread-safe-queue-two-serious-errors\" method=\"post\" name=\"adminForm\" id=\"adminForm\" class=\"submission form-validate\"><div id=\"blogContent\" class=\"blog-content\"><div><div>This program has two serious issues. <strong>Dietmar K\u00fchl<\/strong> and <strong>Frank Birbacher<\/strong> wrote me an e-mail about it. These are their words, which I translated into English. <strong><em>My additions are cursive and bold.<\/em><\/strong><\/div><div>\u00a0<\/div><ol><li>In <code>ThreadSafeQueue::get()<\/code> it is tested by<code> Monitor::wait()<\/code> whether <code>myQueue<\/code> contains an element or waits for an element to be contained. However, the lock is only held inside <code>wait()<\/code>, i.e. in <code>get()<\/code> you cannot be sure that the element is still in <code>myQueue<\/code>: another thread may get the lock and remove the element, resulting in undefined behavior on the call to <code>myQueue.front()<\/code>.<\/li><li>If the copy\/move constructor of<code> T<\/code> throws an exception, the <code>ThreadSafeQueue<\/code> is in an inconsistent state: no member function is active, but the mutex is locked<\/li><\/ol><p>\u00a0<\/p><p>The fix is that<code> Monitor::wait()<\/code> can only be called if a<code> unique_lock<\/code> is held. This can be achieved, for example, by having <code>Monitor<\/code> provide an appropriate (protected?) function that returns a suitable object and requests a reference to it in<code> wait()<\/code>:<\/p><\/div><\/div><\/form><\/div><\/div><\/div><\/div><\/div><\/p>\n\n\n\n<!-- HTML generated using hilite.me --><div style=\"background: #f0f3f3; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;\"><pre style=\"margin: 0; line-height: 125%\"><span style=\"color: #006699; font-weight: bold\">struct<\/span> Monitor {\n   <span style=\"color: #006699; font-weight: bold\">using<\/span> Lock <span style=\"color: #555555\">=<\/span> std<span style=\"color: #555555\">::<\/span>unique_lock<span style=\"color: #555555\">&lt;<\/span>std<span style=\"color: #555555\">::<\/span>mutex<span style=\"color: #555555\">&gt;<\/span>; <span style=\"color: #0099FF; font-style: italic\">\/\/ could be wrapper if you prefer<\/span>\n   [[nodiscard]] Lock receiveGuard() { <span style=\"color: #006699; font-weight: bold\">return<\/span> Lock(monitMutex); }\n   <span style=\"color: #006699; font-weight: bold\">template<\/span> <span style=\"color: #555555\">&lt;<\/span><span style=\"color: #006699; font-weight: bold\">typename<\/span> Predicate<span style=\"color: #555555\">&gt;<\/span>\n   <span style=\"color: #007788; font-weight: bold\">void<\/span> wait(Lock<span style=\"color: #555555\">&amp;<\/span> kerberos, Predicate pred) { monitCond.wait(kerberos, pred); }\n   <span style=\"color: #0099FF; font-style: italic\">\/\/ \u2026<\/span>\n};\n\n<span style=\"color: #006699; font-weight: bold\">template<\/span> <span style=\"color: #555555\">&lt;<\/span><span style=\"color: #006699; font-weight: bold\">typename<\/span> T<span style=\"color: #555555\">&gt;<\/span>\nT ThreadSafeQueue<span style=\"color: #555555\">&lt;<\/span>T<span style=\"color: #555555\">&gt;::<\/span>get() {\n   <span style=\"color: #006699; font-weight: bold\">auto<\/span> kerberos <span style=\"color: #555555\">=<\/span> receiveGuard();\n   wait(kerberos, [<span style=\"color: #006699; font-weight: bold\">this<\/span>]{ <span style=\"color: #006699; font-weight: bold\">return<\/span> not myQueue.empty(); });\n   T rc <span style=\"color: #555555\">=<\/span> std<span style=\"color: #555555\">::<\/span>move(myQueue.front());\n   myqueue.pop();\n   <span style=\"color: #006699; font-weight: bold\">return<\/span> rc;\n}\n<\/pre><\/div>\n\n\n\n<p>This version corrects the exception problem for <code>get()<\/code>. For <code>add()<\/code> you can simply use the monitor object with a <code>lock_guard<\/code>:<\/p>\n\n\n\n<!-- HTML generated using hilite.me --><div style=\"background: #f0f3f3; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;\"><pre style=\"margin: 0; line-height: 125%\"><span style=\"color: #006699; font-weight: bold\">template<\/span> <span style=\"color: #555555\">&lt;<\/span><span style=\"color: #006699; font-weight: bold\">typename<\/span> T<span style=\"color: #555555\">&gt;<\/span>\n<span style=\"color: #007788; font-weight: bold\">void<\/span> add(T val) {\n   {\n        std<span style=\"color: #555555\">::<\/span>lock_guard<span style=\"color: #555555\">&lt;<\/span>Monitor<span style=\"color: #555555\">&gt;<\/span> kerberos(<span style=\"color: #555555\">*<\/span><span style=\"color: #006699; font-weight: bold\">this<\/span>);\n        myqueue.push(std<span style=\"color: #555555\">::<\/span>move(val));\n    }\n    notify_one();\n}\n<\/pre><\/div>\n\n\n\n<p>I would probably wrap the notification in a &#8220;<code>SendGuard<\/code>&#8221; that contains a <code>lock_guard<\/code> and a reference to the <code>condition_variable<\/code> and sends the notification upon destruction:<\/p>\n\n\n\n<!-- HTML generated using hilite.me --><div style=\"background: #f0f3f3; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;\"><pre style=\"margin: 0; line-height: 125%\"><span style=\"color: #006699; font-weight: bold\">class<\/span> <span style=\"color: #00AA88; font-weight: bold\">SendGuard<\/span> {\n    <span style=\"color: #006699; font-weight: bold\">friend<\/span> <span style=\"color: #006699; font-weight: bold\">class<\/span> <span style=\"color: #00AA88; font-weight: bold\">Monitor<\/span>;\n    <span style=\"color: #006699; font-weight: bold\">using<\/span> deleter <span style=\"color: #555555\">=<\/span> decltype([](<span style=\"color: #006699; font-weight: bold\">auto<\/span><span style=\"color: #555555\">&amp;<\/span> cond){ cond<span style=\"color: #555555\">-&gt;<\/span>notify_one(); });\n    std<span style=\"color: #555555\">::<\/span>unique_ptr<span style=\"color: #555555\">&lt;<\/span>std<span style=\"color: #555555\">::<\/span>condition_variable, deleter<span style=\"color: #555555\">&gt;<\/span> notifier;\n    std<span style=\"color: #555555\">::<\/span>lock_guard<span style=\"color: #555555\">&lt;<\/span>std<span style=\"color: #555555\">::<\/span>mutex<span style=\"color: #555555\">&gt;<\/span> kerberos;\n    SendGuard(<span style=\"color: #006699; font-weight: bold\">auto<\/span><span style=\"color: #555555\">&amp;<\/span> mutex, <span style=\"color: #006699; font-weight: bold\">auto<\/span><span style=\"color: #555555\">&amp;<\/span> cond)<span style=\"color: #555555\">:<\/span> notifier(<span style=\"color: #555555\">&amp;<\/span>cond), kerberos(mutex) {}\n};\n<\/pre><\/div>\n\n\n\n<p><em><strong>The move constructor and destructor should still be public and represent the whole interface! This would also make it much easier to use in<\/strong> <code>add()<\/code>:<\/em><\/p>\n\n\n\n<!-- HTML generated using hilite.me --><div style=\"background: #f0f3f3; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;\"><pre style=\"margin: 0; line-height: 125%\"><span style=\"color: #006699; font-weight: bold\">template<\/span> <span style=\"color: #555555\">&lt;<\/span><span style=\"color: #006699; font-weight: bold\">typename<\/span> T<span style=\"color: #555555\">&gt;<\/span>\n<span style=\"color: #007788; font-weight: bold\">void<\/span> add(T val) {\n   <span style=\"color: #006699; font-weight: bold\">auto<\/span> kerberos <span style=\"color: #555555\">=<\/span> sendGuard();\n   myqueue.push(val);\n}\n<\/pre><\/div>\n\n\n\n<p><strong><em>Finally, here is the full implementation of Dietmar. The numbers correspond to the numbers in my monitorObjec.cpp example.<\/em><\/strong><\/p>\n\n\n\n<!-- HTML generated using hilite.me --><div style=\"background: #f0f3f3; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;\"><pre style=\"margin: 0; line-height: 125%\"><span style=\"color: #0099FF; font-style: italic\">\/\/ threadsafequeue1.cpp<\/span>\n\n<span style=\"color: #009999\">#include &lt;condition_variable&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;functional&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;queue&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;iostream&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;mutex&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;random&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;thread&gt;<\/span>\n\n<span style=\"color: #006699; font-weight: bold\">class<\/span> <span style=\"color: #00AA88; font-weight: bold\">Monitor<\/span> {\n<span style=\"color: #9999FF\">public:<\/span>\n    <span style=\"color: #006699; font-weight: bold\">using<\/span> Lock <span style=\"color: #555555\">=<\/span> std<span style=\"color: #555555\">::<\/span>unique_lock<span style=\"color: #555555\">&lt;<\/span>std<span style=\"color: #555555\">::<\/span>mutex<span style=\"color: #555555\">&gt;<\/span>;\n    [[nodiscard]] Lock receiveGuard() {\n        <span style=\"color: #006699; font-weight: bold\">return<\/span> Lock(monitMutex);\n    }\n\n    <span style=\"color: #006699; font-weight: bold\">template<\/span> <span style=\"color: #555555\">&lt;<\/span><span style=\"color: #006699; font-weight: bold\">typename<\/span> Predicate<span style=\"color: #555555\">&gt;<\/span>\n    <span style=\"color: #007788; font-weight: bold\">void<\/span> wait(Lock<span style=\"color: #555555\">&amp;<\/span> kerberos, Predicate pred) {\n        monitCond.wait(kerberos, pred);\n    }\n\n    <span style=\"color: #006699; font-weight: bold\">class<\/span> <span style=\"color: #00AA88; font-weight: bold\">SendGuard<\/span> {\n        <span style=\"color: #006699; font-weight: bold\">friend<\/span> <span style=\"color: #006699; font-weight: bold\">class<\/span> <span style=\"color: #00AA88; font-weight: bold\">Monitor<\/span>;\n        <span style=\"color: #006699; font-weight: bold\">using<\/span> deleter <span style=\"color: #555555\">=<\/span> decltype([](<span style=\"color: #006699; font-weight: bold\">auto<\/span><span style=\"color: #555555\">*<\/span> cond){ cond<span style=\"color: #555555\">-&gt;<\/span>notify_one(); });\n        std<span style=\"color: #555555\">::<\/span>unique_ptr<span style=\"color: #555555\">&lt;<\/span>std<span style=\"color: #555555\">::<\/span>condition_variable, deleter<span style=\"color: #555555\">&gt;<\/span> notifier;\n        std<span style=\"color: #555555\">::<\/span>lock_guard<span style=\"color: #555555\">&lt;<\/span>std<span style=\"color: #555555\">::<\/span>mutex<span style=\"color: #555555\">&gt;<\/span> kerberos;\n        SendGuard(<span style=\"color: #006699; font-weight: bold\">auto<\/span><span style=\"color: #555555\">&amp;<\/span> mutex, <span style=\"color: #006699; font-weight: bold\">auto<\/span><span style=\"color: #555555\">&amp;<\/span> cond)<span style=\"color: #555555\">:<\/span> notifier(<span style=\"color: #555555\">&amp;<\/span>cond), kerberos(mutex) {}\n    };\n\n    SendGuard <span style=\"color: #CC00FF\">sendGuard<\/span>() { <span style=\"color: #006699; font-weight: bold\">return<\/span> {monitMutex, monitCond}; }\n    \n<span style=\"color: #9999FF\">private:<\/span>\n    <span style=\"color: #006699; font-weight: bold\">mutable<\/span> std<span style=\"color: #555555\">::<\/span>mutex monitMutex;\n    <span style=\"color: #006699; font-weight: bold\">mutable<\/span> std<span style=\"color: #555555\">::<\/span>condition_variable monitCond;\n};\n\n<span style=\"color: #006699; font-weight: bold\">template<\/span> <span style=\"color: #555555\">&lt;<\/span><span style=\"color: #006699; font-weight: bold\">typename<\/span> T<span style=\"color: #555555\">&gt;<\/span>                                  <span style=\"color: #0099FF; font-style: italic\">\/\/ (1)<\/span>\n<span style=\"color: #006699; font-weight: bold\">class<\/span> <span style=\"color: #00AA88; font-weight: bold\">ThreadSafeQueue<\/span><span style=\"color: #555555\">:<\/span> <span style=\"color: #006699; font-weight: bold\">public<\/span> Monitor {\n <span style=\"color: #9999FF\">public:<\/span>\n    <span style=\"color: #007788; font-weight: bold\">void<\/span> add(T val){ \n        <span style=\"color: #006699; font-weight: bold\">auto<\/span> kerberos <span style=\"color: #555555\">=<\/span> sendGuard();\n        myQueue.push(val);                             <span style=\"color: #0099FF; font-style: italic\">\/\/ (6)<\/span>\n    }\n    \n    T get(){ \n        <span style=\"color: #006699; font-weight: bold\">auto<\/span> kerberos <span style=\"color: #555555\">=<\/span> receiveGuard();\n        wait(kerberos, [<span style=\"color: #006699; font-weight: bold\">this<\/span>] { <span style=\"color: #006699; font-weight: bold\">return<\/span> <span style=\"color: #555555\">!<\/span> myQueue.empty(); } );  <span style=\"color: #0099FF; font-style: italic\">\/\/ (2)<\/span>\n        <span style=\"color: #006699; font-weight: bold\">auto<\/span> val <span style=\"color: #555555\">=<\/span> myQueue.front();                    <span style=\"color: #0099FF; font-style: italic\">\/\/ (4)<\/span>\n        myQueue.pop();                                 <span style=\"color: #0099FF; font-style: italic\">\/\/ (5)<\/span>\n        <span style=\"color: #006699; font-weight: bold\">return<\/span> val;\n    }\n\n<span style=\"color: #9999FF\">private:<\/span>\n    std<span style=\"color: #555555\">::<\/span>queue<span style=\"color: #555555\">&lt;<\/span>T<span style=\"color: #555555\">&gt;<\/span> myQueue;                            <span style=\"color: #0099FF; font-style: italic\">\/\/ (3)<\/span>\n};\n\n\n<span style=\"color: #006699; font-weight: bold\">class<\/span> <span style=\"color: #00AA88; font-weight: bold\">Dice<\/span> {\n<span style=\"color: #9999FF\">public:<\/span>\n    <span style=\"color: #007788; font-weight: bold\">int<\/span> <span style=\"color: #006699; font-weight: bold\">operator<\/span>()(){ <span style=\"color: #006699; font-weight: bold\">return<\/span> rand(); }\n<span style=\"color: #9999FF\">private:<\/span>\n    std<span style=\"color: #555555\">::<\/span>function<span style=\"color: #555555\">&lt;<\/span><span style=\"color: #007788; font-weight: bold\">int<\/span>()<span style=\"color: #555555\">&gt;<\/span> rand <span style=\"color: #555555\">=<\/span> std<span style=\"color: #555555\">::<\/span>bind(std<span style=\"color: #555555\">::<\/span>uniform_int_distribution<span style=\"color: #555555\">&lt;&gt;<\/span>(<span style=\"color: #FF6600\">1<\/span>, <span style=\"color: #FF6600\">6<\/span>), \n                                          std<span style=\"color: #555555\">::<\/span>default_random_engine());\n};\n\n\n<span style=\"color: #007788; font-weight: bold\">int<\/span> <span style=\"color: #CC00FF\">main<\/span>(){\n    \n    std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&#39;\\n&#39;<\/span>;\n    \n    constexpr <span style=\"color: #006699; font-weight: bold\">auto<\/span> NumberThreads <span style=\"color: #555555\">=<\/span> <span style=\"color: #FF6600\">100<\/span>;\n    \n    ThreadSafeQueue<span style=\"color: #555555\">&lt;<\/span><span style=\"color: #007788; font-weight: bold\">int<\/span><span style=\"color: #555555\">&gt;<\/span> safeQueue;                      <span style=\"color: #0099FF; font-style: italic\">\/\/ (7)<\/span>\n\n    <span style=\"color: #006699; font-weight: bold\">auto<\/span> addLambda <span style=\"color: #555555\">=<\/span> [<span style=\"color: #555555\">&amp;<\/span>safeQueue](<span style=\"color: #007788; font-weight: bold\">int<\/span> val){ safeQueue.add(val);          <span style=\"color: #0099FF; font-style: italic\">\/\/ (8)<\/span>\n                                            std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> val <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&quot; &quot;<\/span>\n                                            <span style=\"color: #555555\">&lt;&lt;<\/span> std<span style=\"color: #555555\">::<\/span>this_thread<span style=\"color: #555555\">::<\/span>get_id() <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&quot;; &quot;<\/span>; \n                                          }; \n    <span style=\"color: #006699; font-weight: bold\">auto<\/span> getLambda <span style=\"color: #555555\">=<\/span> [<span style=\"color: #555555\">&amp;<\/span>safeQueue]{ safeQueue.get(); };  <span style=\"color: #0099FF; font-style: italic\">\/\/ (9)<\/span>\n\n    std<span style=\"color: #555555\">::<\/span>vector<span style=\"color: #555555\">&lt;<\/span>std<span style=\"color: #555555\">::<\/span><span style=\"color: #006699; font-weight: bold\">thread<\/span><span style=\"color: #555555\">&gt;<\/span> addThreads(NumberThreads);\n    Dice dice;\n    <span style=\"color: #006699; font-weight: bold\">for<\/span> (<span style=\"color: #006699; font-weight: bold\">auto<\/span><span style=\"color: #555555\">&amp;<\/span> thr<span style=\"color: #555555\">:<\/span> addThreads) thr <span style=\"color: #555555\">=<\/span> std<span style=\"color: #555555\">::<\/span><span style=\"color: #006699; font-weight: bold\">thread<\/span>(addLambda, dice());\n\n    std<span style=\"color: #555555\">::<\/span>vector<span style=\"color: #555555\">&lt;<\/span>std<span style=\"color: #555555\">::<\/span><span style=\"color: #006699; font-weight: bold\">thread<\/span><span style=\"color: #555555\">&gt;<\/span> getThreads(NumberThreads);\n    <span style=\"color: #006699; font-weight: bold\">for<\/span> (<span style=\"color: #006699; font-weight: bold\">auto<\/span><span style=\"color: #555555\">&amp;<\/span> thr<span style=\"color: #555555\">:<\/span> getThreads) thr <span style=\"color: #555555\">=<\/span> std<span style=\"color: #555555\">::<\/span><span style=\"color: #006699; font-weight: bold\">thread<\/span>(getLambda);\n\n    <span style=\"color: #006699; font-weight: bold\">for<\/span> (<span style=\"color: #006699; font-weight: bold\">auto<\/span><span style=\"color: #555555\">&amp;<\/span> thr<span style=\"color: #555555\">:<\/span> addThreads) thr.join();\n    <span style=\"color: #006699; font-weight: bold\">for<\/span> (<span style=\"color: #006699; font-weight: bold\">auto<\/span><span style=\"color: #555555\">&amp;<\/span> thr<span style=\"color: #555555\">:<\/span> getThreads) thr.join();\n    \n    std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&quot;<\/span><span style=\"color: #CC3300; font-weight: bold\">\\n\\n<\/span><span style=\"color: #CC3300\">&quot;<\/span>;\n     \n}\n<\/pre><\/div>\n\n\n\n<p>As a result of the discussion above, Frank has proposed the following version below, which has a consistent and easy-to-use interface for Monitor.<\/p>\n\n\n\n<!-- HTML generated using hilite.me --><div style=\"background: #f0f3f3; overflow:auto;width:auto; gray;border-width:.1em .1em .1em .8em\"><pre style=\"margin: 0; line-height: 125%\"><span style=\"color: #0099FF; font-style: italic\">\/\/ threadSafeQueue.cpp<\/span>\n\n<span style=\"color: #009999\">#ifndef INCLUDED_PATTERNS_MONITOR2_MONITOR_HPP<\/span>\n<span style=\"color: #009999\">#define INCLUDED_PATTERNS_MONITOR2_MONITOR_HPP<\/span>\n\n<span style=\"color: #009999\">#include &lt;atomic&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;algorithm&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;condition_variable&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;deque&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;iterator&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;mutex&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;stdexcept&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;thread&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;vector&gt;<\/span>\n\n\n<span style=\"color: #006699; font-weight: bold\">class<\/span> <span style=\"color: #00AA88; font-weight: bold\">Monitor<\/span> {\n<span style=\"color: #9999FF\">public:<\/span>\n    <span style=\"color: #006699; font-weight: bold\">struct<\/span> UnlockAndNotify {\n        std<span style=\"color: #555555\">::<\/span>mutex d_mutex;\n        std<span style=\"color: #555555\">::<\/span>condition_variable d_condition;\n\n        <span style=\"color: #007788; font-weight: bold\">void<\/span> <span style=\"color: #CC00FF\">lock<\/span>() { d_mutex.lock(); }\n        <span style=\"color: #007788; font-weight: bold\">void<\/span> <span style=\"color: #CC00FF\">unlock<\/span>() { d_mutex.unlock(); d_condition.notify_one(); }\n    };\n\n<span style=\"color: #9999FF\">private:<\/span>\n    UnlockAndNotify d_combined;\n\n<span style=\"color: #9999FF\">public:<\/span>\n    std<span style=\"color: #555555\">::<\/span>unique_lock<span style=\"color: #555555\">&lt;<\/span>UnlockAndNotify<span style=\"color: #555555\">&gt;<\/span> makeLockWithNotify() {\n        <span style=\"color: #006699; font-weight: bold\">return<\/span> std<span style=\"color: #555555\">::<\/span>unique_lock{d_combined};\n    }\n\n    <span style=\"color: #006699; font-weight: bold\">template<\/span> <span style=\"color: #555555\">&lt;<\/span><span style=\"color: #006699; font-weight: bold\">typename<\/span> PRED<span style=\"color: #555555\">&gt;<\/span>\n    std<span style=\"color: #555555\">::<\/span>unique_lock<span style=\"color: #555555\">&lt;<\/span>std<span style=\"color: #555555\">::<\/span>mutex<span style=\"color: #555555\">&gt;<\/span> makeLockWithWait(PRED waitForCondition) {\n        std<span style=\"color: #555555\">::<\/span>unique_lock lock{d_combined.d_mutex};\n        d_combined.d_condition.wait(lock, waitForCondition);\n        <span style=\"color: #006699; font-weight: bold\">return<\/span> lock;\n    }\n};\n\n<span style=\"color: #006699; font-weight: bold\">class<\/span> <span style=\"color: #00AA88; font-weight: bold\">ThreadQueue<\/span> {\n    Monitor d_monitor;\n    std<span style=\"color: #555555\">::<\/span>deque<span style=\"color: #555555\">&lt;<\/span><span style=\"color: #007788; font-weight: bold\">int<\/span><span style=\"color: #555555\">&gt;<\/span> d_numberQueue;\n\n    <span style=\"color: #006699; font-weight: bold\">auto<\/span> <span style=\"color: #CC00FF\">makeLockWhenNotEmpty<\/span>() {\n        <span style=\"color: #006699; font-weight: bold\">return<\/span> d_monitor.makeLockWithWait([<span style=\"color: #006699; font-weight: bold\">this<\/span>] { <span style=\"color: #006699; font-weight: bold\">return<\/span> <span style=\"color: #555555\">!<\/span>d_numberQueue.empty(); });\n    }\n\n<span style=\"color: #9999FF\">public:<\/span>\n    <span style=\"color: #007788; font-weight: bold\">void<\/span> <span style=\"color: #CC00FF\">addNumber<\/span>(<span style=\"color: #007788; font-weight: bold\">int<\/span> number) {\n        <span style=\"color: #006699; font-weight: bold\">const<\/span> <span style=\"color: #006699; font-weight: bold\">auto<\/span> lock <span style=\"color: #555555\">=<\/span> d_monitor.makeLockWithNotify();\n        d_numberQueue.push_back(number);\n    }\n\n    <span style=\"color: #007788; font-weight: bold\">int<\/span> <span style=\"color: #CC00FF\">removeNumber<\/span>() {\n        <span style=\"color: #006699; font-weight: bold\">const<\/span> <span style=\"color: #006699; font-weight: bold\">auto<\/span> lock <span style=\"color: #555555\">=<\/span> makeLockWhenNotEmpty();\n        <span style=\"color: #006699; font-weight: bold\">const<\/span> <span style=\"color: #006699; font-weight: bold\">auto<\/span> number <span style=\"color: #555555\">=<\/span> d_numberQueue.front();\n        d_numberQueue.pop_front();\n        <span style=\"color: #006699; font-weight: bold\">return<\/span> number;\n    }\n};\n\n<span style=\"color: #009999\">#endif<\/span>\n\n<span style=\"color: #007788; font-weight: bold\">int<\/span> <span style=\"color: #CC00FF\">main<\/span>() {\n   ThreadQueue queue;\n   std<span style=\"color: #555555\">::<\/span>atomic<span style=\"color: #555555\">&lt;<\/span><span style=\"color: #007788; font-weight: bold\">int<\/span><span style=\"color: #555555\">&gt;<\/span> sharedSum{};\n   std<span style=\"color: #555555\">::<\/span>atomic<span style=\"color: #555555\">&lt;<\/span><span style=\"color: #007788; font-weight: bold\">int<\/span><span style=\"color: #555555\">&gt;<\/span> sharedCounter{};\n\n   std<span style=\"color: #555555\">::<\/span>vector<span style=\"color: #555555\">&lt;<\/span>std<span style=\"color: #555555\">::<\/span>jthread<span style=\"color: #555555\">&gt;<\/span> threads;\n   threads.reserve(<span style=\"color: #FF6600\">200<\/span>);\n   std<span style=\"color: #555555\">::<\/span>generate_n(std<span style=\"color: #555555\">::<\/span>back_inserter(threads), <span style=\"color: #FF6600\">100<\/span>, [<span style=\"color: #555555\">&amp;<\/span>] {\n       <span style=\"color: #006699; font-weight: bold\">return<\/span> std<span style=\"color: #555555\">::<\/span>jthread{[<span style=\"color: #555555\">&amp;<\/span>] { sharedSum <span style=\"color: #555555\">+=<\/span> queue.removeNumber(); }};\n   });\n   std<span style=\"color: #555555\">::<\/span>generate_n(std<span style=\"color: #555555\">::<\/span>back_inserter(threads), <span style=\"color: #FF6600\">100<\/span>, [<span style=\"color: #555555\">&amp;<\/span>] {\n       <span style=\"color: #006699; font-weight: bold\">return<\/span> std<span style=\"color: #555555\">::<\/span>jthread{[<span style=\"color: #555555\">&amp;<\/span>] { queue.addNumber(<span style=\"color: #555555\">++<\/span>sharedCounter); }};\n   });\n\n   threads.clear(); <span style=\"color: #0099FF; font-style: italic\">\/\/ wait for all threads to finish<\/span>\n   <span style=\"color: #006699; font-weight: bold\">if<\/span> (sharedSum.load() <span style=\"color: #555555\">!=<\/span> <span style=\"color: #FF6600\">5050<\/span>) {\n       <span style=\"color: #006699; font-weight: bold\">throw<\/span> std<span style=\"color: #555555\">::<\/span>logic_error(<span style=\"color: #CC3300\">&quot;Wrong result for sum of 1..100&quot;<\/span>);\n   }\n}\n<\/pre><\/div>\n\n\n\n<p>The implementation of the monitor pattern here is based on the flexibility of <code>std::unique_lock<\/code> through its template parameter. &nbsp;All of the std RAII lock&nbsp;guards can be used with any class that has <code>lock()<\/code> and <code>unlock()<\/code> methods. &nbsp;The <code>UnlockAndNotify<\/code> class implements this interface and notifies its&nbsp;condition variable from within the <code>unlock()<\/code> method. &nbsp;On top of that, the <code>Monitor<\/code> class provides a reduced public interface to create two different kinds&nbsp;of locks, one with notification and one without, by creating a <code>std::unique_lock<\/code> on either the whole <code>UnlockAndNotify<\/code> instance or just the contained&nbsp;<code>std::mutex<\/code>.<br class=\"\"><br class=\"\">On the choice of <code>std::unique_lock<\/code> versus <code>std::lock_guard<\/code> I (<strong><em>Frank<\/em><\/strong>) prefer the <code>unique_lock<\/code> in the interface. &nbsp;This choice allows the user of the <code>Monitor<\/code> class&nbsp;more flexibility. &nbsp;I value this flexibility higher than a possible performance difference to<code> lock_guard<\/code> which anyway needs to be measured first. &nbsp;I&nbsp;acknowledge that the given examples don&#8217;t make use of this extra flexibility.<\/p>\n\n\n\n<p><strong><em>Afterward, Dietmar further developed Frank&#8217;s idea: here, the protected data is kept in the Monitor, making it harder to access it unprotected.<\/em><\/strong><\/p>\n\n\n\n<!-- HTML generated using hilite.me --><div style=\"background: #f0f3f3; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;\"><pre style=\"margin: 0; line-height: 125%\"><span style=\"color: #0099FF; font-style: italic\">\/\/ threadsafequeue2.cpp<\/span>\n\n<span style=\"color: #009999\">#ifndef INCLUDED_PATTERNS_MONITOR3_MONITOR_HPP<\/span>\n<span style=\"color: #009999\">#define INCLUDED_PATTERNS_MONITOR3_MONITOR_HPP<\/span>\n\n<span style=\"color: #009999\">#include &lt;algorithm&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;atomic&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;condition_variable&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;deque&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;functional&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;iostream&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;iterator&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;mutex&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;random&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;stdexcept&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;thread&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;tuple&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;vector&gt;<\/span>\n\n<span style=\"color: #006699; font-weight: bold\">namespace<\/span> patterns<span style=\"color: #555555\">::<\/span>monitor3 {\n\n<span style=\"color: #006699; font-weight: bold\">template<\/span> <span style=\"color: #555555\">&lt;<\/span><span style=\"color: #006699; font-weight: bold\">typename<\/span> T<span style=\"color: #555555\">&gt;<\/span>\n<span style=\"color: #006699; font-weight: bold\">class<\/span> <span style=\"color: #00AA88; font-weight: bold\">Monitor<\/span> {\n<span style=\"color: #9999FF\">public:<\/span>\n   <span style=\"color: #006699; font-weight: bold\">struct<\/span> UnlockAndNotify {\n       std<span style=\"color: #555555\">::<\/span>mutex d_mutex;\n       std<span style=\"color: #555555\">::<\/span>condition_variable d_condition;\n   \n       <span style=\"color: #007788; font-weight: bold\">void<\/span> <span style=\"color: #CC00FF\">lock<\/span>() { d_mutex.lock(); }\n       <span style=\"color: #007788; font-weight: bold\">void<\/span> <span style=\"color: #CC00FF\">unlock<\/span>() { d_mutex.unlock(); d_condition.notify_one(); }\n   };\n\n<span style=\"color: #9999FF\">private:<\/span>\n   <span style=\"color: #006699; font-weight: bold\">mutable<\/span> UnlockAndNotify d_combined;\n   <span style=\"color: #006699; font-weight: bold\">mutable<\/span> T               d_data;\n\n<span style=\"color: #9999FF\">public:<\/span>\n   std<span style=\"color: #555555\">::<\/span>tuple<span style=\"color: #555555\">&lt;<\/span>T<span style=\"color: #555555\">&amp;<\/span>, std<span style=\"color: #555555\">::<\/span>unique_lock<span style=\"color: #555555\">&lt;<\/span>UnlockAndNotify<span style=\"color: #555555\">&gt;&gt;<\/span> makeProducerLock() <span style=\"color: #006699; font-weight: bold\">const<\/span> {\n       <span style=\"color: #006699; font-weight: bold\">return<\/span> { d_data, std<span style=\"color: #555555\">::<\/span>unique_lock{d_combined} };\n   }\n\n   <span style=\"color: #006699; font-weight: bold\">template<\/span> <span style=\"color: #555555\">&lt;<\/span><span style=\"color: #006699; font-weight: bold\">typename<\/span> PRED<span style=\"color: #555555\">&gt;<\/span>\n   std<span style=\"color: #555555\">::<\/span>tuple<span style=\"color: #555555\">&lt;<\/span>T<span style=\"color: #555555\">&amp;<\/span>, std<span style=\"color: #555555\">::<\/span>unique_lock<span style=\"color: #555555\">&lt;<\/span>std<span style=\"color: #555555\">::<\/span>mutex<span style=\"color: #555555\">&gt;&gt;<\/span> makeConsumerLockWhen(PRED predicate) <span style=\"color: #006699; font-weight: bold\">const<\/span> {\n       std<span style=\"color: #555555\">::<\/span>unique_lock lock{d_combined.d_mutex};\n       d_combined.d_condition.wait(lock, [<span style=\"color: #006699; font-weight: bold\">this<\/span>, predicate]{ <span style=\"color: #006699; font-weight: bold\">return<\/span> predicate(d_data); });\n       <span style=\"color: #006699; font-weight: bold\">return<\/span> { d_data, std<span style=\"color: #555555\">::<\/span>move(lock) };\n   }\n};\n\n<span style=\"color: #006699; font-weight: bold\">template<\/span> <span style=\"color: #555555\">&lt;<\/span><span style=\"color: #006699; font-weight: bold\">typename<\/span> T<span style=\"color: #555555\">&gt;<\/span>\n<span style=\"color: #006699; font-weight: bold\">class<\/span> <span style=\"color: #00AA88; font-weight: bold\">ThreadQueue<\/span> {\n   Monitor<span style=\"color: #555555\">&lt;<\/span>std<span style=\"color: #555555\">::<\/span>deque<span style=\"color: #555555\">&lt;<\/span>T<span style=\"color: #555555\">&gt;&gt;<\/span> d_monitor;\n\n<span style=\"color: #9999FF\">public:<\/span>\n   <span style=\"color: #007788; font-weight: bold\">void<\/span> <span style=\"color: #CC00FF\">add<\/span>(T number) {\n       <span style=\"color: #006699; font-weight: bold\">auto<\/span>[numberQueue, lock] <span style=\"color: #555555\">=<\/span> d_monitor.makeProducerLock();\n       numberQueue.push_back(number);\n   }\n\n   T <span style=\"color: #CC00FF\">remove<\/span>() {\n       <span style=\"color: #006699; font-weight: bold\">auto<\/span>[numberQueue, lock] <span style=\"color: #555555\">=<\/span> d_monitor.makeConsumerLockWhen([](<span style=\"color: #006699; font-weight: bold\">auto<\/span><span style=\"color: #555555\">&amp;<\/span> numberQueue) { <span style=\"color: #006699; font-weight: bold\">return<\/span> <span style=\"color: #555555\">!<\/span>numberQueue.empty(); });\n       <span style=\"color: #006699; font-weight: bold\">const<\/span> <span style=\"color: #006699; font-weight: bold\">auto<\/span> number <span style=\"color: #555555\">=<\/span> numberQueue.front();\n       numberQueue.pop_front();\n       <span style=\"color: #006699; font-weight: bold\">return<\/span> number;\n   }\n};\n}\n\n<span style=\"color: #009999\">#endif<\/span>\n\n<span style=\"color: #006699; font-weight: bold\">class<\/span> <span style=\"color: #00AA88; font-weight: bold\">Dice<\/span> {\n<span style=\"color: #9999FF\">public:<\/span>\n    <span style=\"color: #007788; font-weight: bold\">int<\/span> <span style=\"color: #006699; font-weight: bold\">operator<\/span>()(){ <span style=\"color: #006699; font-weight: bold\">return<\/span> rand(); }\n<span style=\"color: #9999FF\">private:<\/span>\n    std<span style=\"color: #555555\">::<\/span>function<span style=\"color: #555555\">&lt;<\/span><span style=\"color: #007788; font-weight: bold\">int<\/span>()<span style=\"color: #555555\">&gt;<\/span> rand <span style=\"color: #555555\">=<\/span> std<span style=\"color: #555555\">::<\/span>bind(std<span style=\"color: #555555\">::<\/span>uniform_int_distribution<span style=\"color: #555555\">&lt;&gt;<\/span>(<span style=\"color: #FF6600\">1<\/span>, <span style=\"color: #FF6600\">6<\/span>), \n                                          std<span style=\"color: #555555\">::<\/span>default_random_engine());\n};\n\n<span style=\"color: #007788; font-weight: bold\">int<\/span> <span style=\"color: #CC00FF\">main<\/span>(){\n    \n    std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&#39;\\n&#39;<\/span>;\n    \n    constexpr <span style=\"color: #006699; font-weight: bold\">auto<\/span> NumberThreads <span style=\"color: #555555\">=<\/span> <span style=\"color: #FF6600\">100<\/span>;\n    \n    patterns<span style=\"color: #555555\">::<\/span>monitor3<span style=\"color: #555555\">::<\/span>ThreadQueue<span style=\"color: #555555\">&lt;<\/span><span style=\"color: #007788; font-weight: bold\">int<\/span><span style=\"color: #555555\">&gt;<\/span> safeQueue;                     \n\n    <span style=\"color: #006699; font-weight: bold\">auto<\/span> addLambda <span style=\"color: #555555\">=<\/span> [<span style=\"color: #555555\">&amp;<\/span>safeQueue](<span style=\"color: #007788; font-weight: bold\">int<\/span> val){ safeQueue.add(val);         \n                                            std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> val <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&quot; &quot;<\/span>\n                                            <span style=\"color: #555555\">&lt;&lt;<\/span> std<span style=\"color: #555555\">::<\/span>this_thread<span style=\"color: #555555\">::<\/span>get_id() <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&quot;; &quot;<\/span>; \n                                          }; \n    <span style=\"color: #006699; font-weight: bold\">auto<\/span> getLambda <span style=\"color: #555555\">=<\/span> [<span style=\"color: #555555\">&amp;<\/span>safeQueue]{ safeQueue.remove(); };  \n\n    std<span style=\"color: #555555\">::<\/span>vector<span style=\"color: #555555\">&lt;<\/span>std<span style=\"color: #555555\">::<\/span><span style=\"color: #006699; font-weight: bold\">thread<\/span><span style=\"color: #555555\">&gt;<\/span> addThreads(NumberThreads);\n    Dice dice;\n    <span style=\"color: #006699; font-weight: bold\">for<\/span> (<span style=\"color: #006699; font-weight: bold\">auto<\/span><span style=\"color: #555555\">&amp;<\/span> thr<span style=\"color: #555555\">:<\/span> addThreads) thr <span style=\"color: #555555\">=<\/span> std<span style=\"color: #555555\">::<\/span><span style=\"color: #006699; font-weight: bold\">thread<\/span>(addLambda, dice());\n\n    std<span style=\"color: #555555\">::<\/span>vector<span style=\"color: #555555\">&lt;<\/span>std<span style=\"color: #555555\">::<\/span><span style=\"color: #006699; font-weight: bold\">thread<\/span><span style=\"color: #555555\">&gt;<\/span> getThreads(NumberThreads);\n    <span style=\"color: #006699; font-weight: bold\">for<\/span> (<span style=\"color: #006699; font-weight: bold\">auto<\/span><span style=\"color: #555555\">&amp;<\/span> thr<span style=\"color: #555555\">:<\/span> getThreads) thr <span style=\"color: #555555\">=<\/span> std<span style=\"color: #555555\">::<\/span><span style=\"color: #006699; font-weight: bold\">thread<\/span>(getLambda);\n\n    <span style=\"color: #006699; font-weight: bold\">for<\/span> (<span style=\"color: #006699; font-weight: bold\">auto<\/span><span style=\"color: #555555\">&amp;<\/span> thr<span style=\"color: #555555\">:<\/span> addThreads) thr.join();\n    <span style=\"color: #006699; font-weight: bold\">for<\/span> (<span style=\"color: #006699; font-weight: bold\">auto<\/span><span style=\"color: #555555\">&amp;<\/span> thr<span style=\"color: #555555\">:<\/span> getThreads) thr.join();\n    \n    std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&quot;<\/span><span style=\"color: #CC3300; font-weight: bold\">\\n\\n<\/span><span style=\"color: #CC3300\">&quot;<\/span>;\n     \n}\n<\/pre><\/div>\n\n\n\n<p>Once more, thanks a lot to&nbsp;<strong>Frank<\/strong>&nbsp;and&nbsp;<strong>Dietmar<\/strong>. I didn&#8217;t want to prove, with my erroneous implementation of a thread-safe queue in my previous post, that concurrency is hard to get right. I&#8217;m particularly annoyed that I don&#8217;t put the mutex inside a lock (error 2). I teach this in my C++ classes: NNM (No Naked Mutex).<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h1-what-s-next\">What&#8217;s next?<\/h2>\n\n\n\n<p>In my next post, I dive into the future of C++: C++23.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In my last post &#8220;Monitor Object&#8221;&nbsp; I implemented a thread-safe queue. I made two serious errors. Sorry. Today, I will fix these issues. First, I want to show you again the erroneous implementation from my last post to understand the context. \/\/ monitorObject.cpp #include &lt;condition_variable&gt; #include &lt;functional&gt; #include &lt;queue&gt; #include &lt;iostream&gt; #include &lt;mutex&gt; #include &lt;random&gt; [&hellip;]<\/p>\n","protected":false},"author":21,"featured_media":7662,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[379],"tags":[],"class_list":["post-7661","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-patterns"],"_links":{"self":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/7661","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/users\/21"}],"replies":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/comments?post=7661"}],"version-history":[{"count":5,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/7661\/revisions"}],"predecessor-version":[{"id":8039,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/7661\/revisions\/8039"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media\/7662"}],"wp:attachment":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media?parent=7661"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=7661"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=7661"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}