{"id":5447,"date":"2018-05-24T07:33:04","date_gmt":"2018-05-24T07:33:04","guid":{"rendered":"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-the-remaining-rules-to-concurrency\/"},"modified":"2023-06-26T11:50:38","modified_gmt":"2023-06-26T11:50:38","slug":"c-core-guidelines-the-remaining-rules-to-concurrency","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-the-remaining-rules-to-concurrency\/","title":{"rendered":"C++ Core Guidelines: More Traps in the Concurrency"},"content":{"rendered":"<p>Concurrency provides many ways to shoot yourself in the foot. The rules for today help you to know these dangers and to overcome them.<\/p>\n<p><!--more--><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5441\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/05\/trap.png\" alt=\"trap\" width=\"700\" height=\"447\" style=\"display: block; margin-left: auto; margin-right: auto;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/05\/trap.png 1280w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/05\/trap-300x192.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/05\/trap-1024x654.png 1024w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/05\/trap-768x491.png 768w\" sizes=\"auto, (max-width: 700px) 100vw, 700px\" \/><\/p>\n<p>First, here are three rules for this post.<\/p>\n<ul>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rconc-data-by-value\">CP.31: Pass small amounts of data between threads by value, rather than by reference or pointer<\/a><\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rconc-shared\">CP.32: To share ownership between unrelated <code class=\"highlighter-rouge no-highlight\">thread<\/code>s use <code class=\"highlighter-rouge no-highlight\">shared_ptr<\/code><\/a><\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rconc-create\">CP.41: Minimize thread creation and destruction<\/a><\/li>\n<\/ul>\n<p>They are more rules which I ignore because they have no content.<\/p>\n<h3><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rconc-data-by-value\">CP.31: Pass small amounts of data between threads by value, rather than by reference or pointer<\/a><\/h3>\n<p>This rule is quite apparent; therefore, I can make it short. Passing data to a thread by value immediately gives you two benefits:<\/p>\n<ol>\n<li>There is no sharing and therefore, no data race is possible. The requirements for a data race are mutable, shared state. Read the details here: <a href=\"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-rules-for-concurrency-and-parallelism\">C++ Core Guidelines: Rules for Concurrency and Parallelism<\/a>.<\/li>\n<li>You do have not to care about the lifetime of the data. The data stays alive for the lifetime of the created thread. This is, in particular, important when you detach a thread: <a href=\"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-taking-care-of-your-child-thread\">C++ Core Guidelines: Taking Care of your Child.<\/a><\/li>\n<\/ol>\n<p>Of course, the crucial question is: What does a small amount of data mean? The C++ core guidelines are not clear on this point. In rule <a href=\"https:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rf-in\">F.16 For \u201cin\u201d parameters, pass cheaply-copied types by value and others by reference to <\/a><code class=\"highlighter-rouge no-highlight\"><a href=\"https:\/\/www.modernescpp.com\/F.16:%20For%20\u201cin\u201d%20parameters,%20pass%20cheaply-copied%20types%20by%20value%20and%20others%20by%20reference%20to%20const\">const to functions<\/a>, <\/code>the C++ core guidelines states that <span style=\"font-family: courier new, courier;\">4 * sizeof(int)<\/span> is a rule of thumb for functions. Meaning smaller than <span style=\"font-family: courier new, courier;\">4 * sizeof(int)<\/span> should be passed by value; bigger than <span style=\"font-family: courier new, courier;\">4 * sizeof(int)<\/span> by reference or pointer.<\/p>\n<p>In the end, you have to measure the performance if necessary.<\/p>\n<\/p>\n<h3><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rconc-shared\">CP.32: To share ownership between unrelated <code class=\"highlighter-rouge no-highlight\">thread<\/code>s use <code class=\"highlighter-rouge no-highlight\">shared_ptr<\/code><\/a><\/h3>\n<p>Imagine you have an object which you want to share between unrelated threads. The critical question is, who is the object&#8217;s owner and, therefore, responsible for releasing the memory? Now you can choose between a memory leak if you don&#8217;t deallocate the memory or undefined behavior because you invoked delete more than once. Most of the time, the undefined behavior ends in a runtime crash.<\/p>\n<p>&nbsp;<\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #0099ff; font-style: italic;\">\/\/ threadSharesOwnership.cpp<\/span>\r\n\r\n<span style=\"color: #009999;\">#include &lt;iostream&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;thread&gt;<\/span>\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">using<\/span> <span style=\"color: #006699; font-weight: bold;\">namespace<\/span> std<span style=\"color: #555555;\">::<\/span>literals<span style=\"color: #555555;\">::<\/span>chrono_literals;\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> MyInt{\r\n  <span style=\"color: #007788; font-weight: bold;\">int<\/span> val{<span style=\"color: #ff6600;\">2017<\/span>};\r\n  <span style=\"color: #555555;\">~<\/span>MyInt(){                                 <span style=\"color: #0099ff; font-style: italic;\">\/\/ (4)<\/span>\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"Good Bye\"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;   <span style=\"color: #0099ff; font-style: italic;\"><\/span>\r\n  }\r\n};\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">showNumber<\/span>(MyInt<span style=\"color: #555555;\">*<\/span> myInt){\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> myInt<span style=\"color: #555555;\">-&gt;<\/span>val <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n}\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">threadCreator<\/span>(){\r\n    MyInt<span style=\"color: #555555;\">*<\/span> tmpInt<span style=\"color: #555555;\">=<\/span> <span style=\"color: #006699; font-weight: bold;\">new<\/span> MyInt;             <span style=\"color: #0099ff; font-style: italic;\">\/\/ (1)<\/span>\r\n    \r\n    std<span style=\"color: #555555;\">::<\/span><span style=\"color: #006699; font-weight: bold;\">thread<\/span> t1(showNumber, tmpInt);   <span style=\"color: #0099ff; font-style: italic;\">\/\/ (2)<\/span>\r\n    std<span style=\"color: #555555;\">::<\/span><span style=\"color: #006699; font-weight: bold;\">thread<\/span> t2(showNumber, tmpInt);   <span style=\"color: #0099ff; font-style: italic;\">\/\/ (3)<\/span>\r\n    \r\n    t1.detach();\r\n    t2.detach();\r\n}\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">main<\/span>(){<br \/><br \/>    std::cout &lt;&lt; std::endl;<br \/>\r\n    threadCreator();\r\n    std<span style=\"color: #555555;\">::<\/span>this_thread<span style=\"color: #555555;\">::<\/span>sleep_for(<span style=\"color: #ff6600;\">1<\/span>s);<br \/><br \/>    std::cout &lt;&lt; std::endl; <br \/>\r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>Bear with me. The example is intentionally so easy. I let the main thread sleep for one second to be sure that it outlives the lifetime of the child threads <span style=\"font-family: courier new, courier;\">t1<\/span> and <span style=\"font-family: courier new, courier;\">t2.<\/span> This is, of course, no appropriate synchronization, but it helps me to make my point. The vital issue of the program is: Who is responsible for the deletion of <span style=\"font-family: courier new, courier;\">tmpInt<\/span> (1)? Thread <span style=\"font-family: courier new, courier;\">t1<\/span> (2), thread<span style=\"font-family: courier new, courier;\"> t2<\/span> (3), or the function (main thread) itself. Because I can not forecast how long each thread runs, I decided to go with a memory leak. Consequentially, the destructor of <span style=\"font-family: courier new, courier;\">MyInt<\/span> (4) is never called:<\/p>\n<p>&nbsp;<img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5442\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/05\/threadSharesOwnership.png\" alt=\"threadSharesOwnership\" width=\"400\" height=\"183\" style=\"display: block; margin-left: auto; margin-right: auto;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/05\/threadSharesOwnership.png 460w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/05\/threadSharesOwnership-300x138.png 300w\" sizes=\"auto, (max-width: 400px) 100vw, 400px\" \/><\/p>\n<p>The lifetime issues are quite easy to handle if I use a <span style=\"font-family: courier new, courier;\">std::shared_ptr<\/span>.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5443\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/05\/threadSharesOwnershipSharedPtr.png\" alt=\"threadSharesOwnershipSharedPtr\" width=\"400\" height=\"177\" style=\"display: block; margin-left: auto; margin-right: auto;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/05\/threadSharesOwnershipSharedPtr.png 527w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/05\/threadSharesOwnershipSharedPtr-300x133.png 300w\" sizes=\"auto, (max-width: 400px) 100vw, 400px\" \/><\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #0099ff; font-style: italic;\">\/\/ threadSharesOwnershipSharedPtr.cpp<\/span>\r\n\r\n<span style=\"color: #009999;\">#include &lt;iostream&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;memory&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;thread&gt;<\/span>\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">using<\/span> <span style=\"color: #006699; font-weight: bold;\">namespace<\/span> std<span style=\"color: #555555;\">::<\/span>literals<span style=\"color: #555555;\">::<\/span>chrono_literals;\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> MyInt{\r\n  <span style=\"color: #007788; font-weight: bold;\">int<\/span> val{<span style=\"color: #ff6600;\">2017<\/span>};\r\n  <span style=\"color: #555555;\">~<\/span>MyInt(){\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"Good Bye\"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n  }\r\n};\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">showNumber<\/span>(std<span style=\"color: #555555;\">::<\/span>shared_ptr<span style=\"color: #555555;\">&lt;<\/span>MyInt<span style=\"color: #555555;\">&gt;<\/span> myInt){    <span style=\"color: #0099ff; font-style: italic;\">\/\/ (2)<\/span>\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> myInt<span style=\"color: #555555;\">-&gt;<\/span>val <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n}\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">threadCreator<\/span>(){\r\n    <span style=\"color: #006699; font-weight: bold;\">auto<\/span> sharedPtr <span style=\"color: #555555;\">=<\/span> std<span style=\"color: #555555;\">::<\/span>make_shared<span style=\"color: #555555;\">&lt;<\/span>MyInt<span style=\"color: #555555;\">&gt;<\/span>();    <span style=\"color: #0099ff; font-style: italic;\">\/\/ (1)<\/span>\r\n    \r\n    std<span style=\"color: #555555;\">::<\/span><span style=\"color: #006699; font-weight: bold;\">thread<\/span> t1(showNumber, sharedPtr);\r\n    std<span style=\"color: #555555;\">::<\/span><span style=\"color: #006699; font-weight: bold;\">thread<\/span> t2(showNumber, sharedPtr);\r\n    \r\n    t1.detach();\r\n    t2.detach();\r\n}\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">main<\/span>(){\r\n    \r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n    \r\n    threadCreator();\r\n    std<span style=\"color: #555555;\">::<\/span>this_thread<span style=\"color: #555555;\">::<\/span>sleep_for(<span style=\"color: #ff6600;\">1<\/span>s);\r\n    \r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n    \r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>Two small changes to the source code were necessary. First, the pointer in (1) became a <span style=\"font-family: courier new, courier;\">std::shared_ptr<\/span>; second, the function <span style=\"font-family: courier new, courier;\">showNumber <\/span>takes a smart pointer instead of a plain pointer<span style=\"font-family: courier new, courier;\">. <br \/><\/span><\/p>\n<h3><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rconc-create\">CP.41: Minimize thread creation and destruction<\/a><\/h3>\n<p>How expensive is a thread? Quite expensive! This is the issue behind this rule. Let me first talk about the usual size of a thread and then the costs of its creation.<\/p>\n<h4>Size<\/h4>\n<p>A <span style=\"font-family: courier new, courier;\">std::thread i<\/span>s a thin wrapper around the native thread. This means I&#8217;m interested in the size of Windows and POSIX threads.<\/p>\n<ul>\n<li>Windows systems: the post <a href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/windows\/desktop\/ms686774(v=vs.85).aspx\">Thread Stack Size<\/a> gave me the answer: 1 MB.<\/li>\n<li>POSIX systems: the<span style=\"font-family: courier new, courier;\"><\/span> <a href=\"http:\/\/man7.org\/linux\/man-pages\/man3\/pthread_create.3.html\"><span style=\"font-family: courier new, courier;\">pthread_create<\/span><\/a> man-page provides me with the answer: 2MB. These is the sizes for the i386 and x86_64 architectures. If you want to know the sizes for further architectures that support POSIX, here are they:<\/li>\n<\/ul>\n<p>&nbsp;<img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5444\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/05\/threadStackSize.png\" alt=\"threadStackSize\" width=\"250\" height=\"274\" style=\"display: block; margin-left: auto; margin-right: auto;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/05\/threadStackSize.png 367w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/05\/threadStackSize-273x300.png 273w\" sizes=\"auto, (max-width: 250px) 100vw, 250px\" \/><\/p>\n<h4>Creation<\/h4>\n<p>I didn&#8217;t find numbers on how long it takes to create a thread. I made a simple performance test on Linux and Windows to get a gut feeling.<\/p>\n<p>I used GCC 6.2.1 on a desktop and cl.exe on a laptop for my performance tests. The cl.exe is part of Microsoft Visual Studio 2017. I compiled the programs with maximum optimization. This means on Linux, the flag <span style=\"font-family: courier new, courier;\">O3<\/span> and Windows <span style=\"font-family: courier new, courier;\">Ox<\/span>.<\/p>\n<p>Here is my small test program.<\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #0099ff; font-style: italic;\">\/\/ threadCreationPerformance.cpp<\/span>\r\n\r\n<span style=\"color: #009999;\">#include &lt;chrono&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;iostream&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;thread&gt;<\/span>\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">static<\/span> <span style=\"color: #006699; font-weight: bold;\">const<\/span> <span style=\"color: #007788; font-weight: bold;\">long<\/span> <span style=\"color: #007788; font-weight: bold;\">long<\/span> numThreads<span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">1000000<\/span>;\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">main<\/span>(){\r\n\r\n    <span style=\"color: #006699; font-weight: bold;\">auto<\/span> start <span style=\"color: #555555;\">=<\/span> std<span style=\"color: #555555;\">::<\/span>chrono<span style=\"color: #555555;\">::<\/span>system_clock<span style=\"color: #555555;\">::<\/span>now();\r\n\r\n    <span style=\"color: #006699; font-weight: bold;\">for<\/span> (<span style=\"color: #006699; font-weight: bold;\">volatile<\/span> <span style=\"color: #007788; font-weight: bold;\">int<\/span> i <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">0<\/span>; i <span style=\"color: #555555;\">&lt;<\/span> numThreads; <span style=\"color: #555555;\">++<\/span>i) std<span style=\"color: #555555;\">::<\/span><span style=\"color: #006699; font-weight: bold;\">thread<\/span>([]{}).detach();  <span style=\"color: #0099ff; font-style: italic;\">\/\/ (1)<\/span>\r\n\r\n    std<span style=\"color: #555555;\">::<\/span>chrono<span style=\"color: #555555;\">::<\/span>duration<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">double<\/span><span style=\"color: #555555;\">&gt;<\/span> dur<span style=\"color: #555555;\">=<\/span> std<span style=\"color: #555555;\">::<\/span>chrono<span style=\"color: #555555;\">::<\/span>system_clock<span style=\"color: #555555;\">::<\/span>now() <span style=\"color: #555555;\">-<\/span> start;\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"time: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> dur.count() <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\" seconds\"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n\r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>The program creates 1 million threads that execute an empty lambda function (1). These are the numbers for Linux and Windows:<\/p>\n<h5><strong>Linux:<\/strong><\/h5>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5445\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/05\/threadCreationLinux.png\" alt=\"threadCreationLinux\" width=\"400\" height=\"247\" style=\"display: block; margin-left: auto; margin-right: auto;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/05\/threadCreationLinux.png 503w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/05\/threadCreationLinux-300x185.png 300w\" sizes=\"auto, (max-width: 400px) 100vw, 400px\" \/><\/p>\n<p>This means that creating a thread took about 14.5 sec \/ 1000000 = <strong>14.5 microseconds on Linux<\/strong>.<\/p>\n<h5><strong>Windows:<\/strong><\/h5>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5446\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/05\/threadCreationWindows.png\" alt=\"threadCreationWindows\" width=\"400\" height=\"295\" style=\"display: block; margin-left: auto; margin-right: auto;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/05\/threadCreationWindows.png 1096w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/05\/threadCreationWindows-300x221.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/05\/threadCreationWindows-1024x755.png 1024w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/05\/threadCreationWindows-768x566.png 768w\" sizes=\"auto, (max-width: 400px) 100vw, 400px\" \/><\/p>\n<p>It took about 44 sec \/ 1000000 = <strong>44 microseconds on Windows.<\/strong><\/p>\n<p>To put it the other way around. In one second, you can create about 69 thousand threads on Linux and 23 thousand on Windows<strong>.<\/strong><\/p>\n<h2>What&#8217;s next?<\/h2>\n<p>What is the easiest way to shoot yourself in the foot? Use a condition variable! Don&#8217;t you believe it? Wait for the <a href=\"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-be-aware-of-the-traps-of-condition-variables\">next post<\/a>!<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Concurrency provides many ways to shoot yourself in the foot. The rules for today help you to know these dangers and to overcome them.<\/p>\n","protected":false},"author":21,"featured_media":5441,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[372],"tags":[400],"class_list":["post-5447","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-modern-c","tag-shared_ptr"],"_links":{"self":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5447","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=5447"}],"version-history":[{"count":1,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5447\/revisions"}],"predecessor-version":[{"id":6826,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5447\/revisions\/6826"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media\/5441"}],"wp:attachment":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media?parent=5447"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=5447"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=5447"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}