{"id":5430,"date":"2018-04-27T19:06:36","date_gmt":"2018-04-27T19:06:36","guid":{"rendered":"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-more-rules-to-concurrency-and-parallelism\/"},"modified":"2023-06-26T11:52:00","modified_gmt":"2023-06-26T11:52:00","slug":"c-core-guidelines-more-rules-to-concurrency-and-parallelism","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-more-rules-to-concurrency-and-parallelism\/","title":{"rendered":"C++ Core Guidelines: More Rules about Concurrency and Parallelism"},"content":{"rendered":"<p>Writing multithreading programs is hard, even harder if the program should be correct. The rules of the C++ Core Guidelines guide you to writing correct programs. The rules of this post will deal with data races, sharing of data, tasks, and the infamous keyword volatile.<\/p>\n<p><!--more--><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5429\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/04\/thread-841607_640.jpg\" alt=\"thread 841607 640\" style=\"display: block; margin-left: auto; margin-right: auto;\" width=\"640\" height=\"426\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/04\/thread-841607_640.jpg 640w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/04\/thread-841607_640-300x200.jpg 300w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/p>\n<p>&nbsp;Here are the five rules for more details.<\/p>\n<ul>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rconc-races\">CP.2: Avoid data races<\/a><\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rconc-data\">CP.3: Minimize explicit sharing of writable data<\/a><\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rconc-task\">CP.4: Think in terms of tasks, rather than threads<\/a><\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rconc-volatile\">CP.8: Don\u2019t try to use <code class=\"highlighter-rouge no-highlight\">volatile<\/code> for synchronization<\/a><\/li>\n<\/ul>\n<p>Let me directly jump into the first rule.<\/p>\n<h3><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rconc-races\">CP.2: Avoid data races<\/a><\/h3>\n<p>I already defined the term data race in the<a href=\"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-rules-for-concurrency-and-parallelism\"> last post<\/a>; therefore, I can make it short. A data race is a concurrent writing and reading of data. The effect is undefined behavior. The C++&nbsp; Core Guidelines provide a typical example of a data race: a static variable.<\/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: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">get_id<\/span>() {\r\n  <span style=\"color: #006699; font-weight: bold;\">static<\/span> <span style=\"color: #007788; font-weight: bold;\">int<\/span> id <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">1<\/span>;\r\n  <span style=\"color: #006699; font-weight: bold;\">return<\/span> id<span style=\"color: #555555;\">++<\/span>;\r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>What can go wrong? For example, thread A and thread B read the same value, k for id. Afterward, thread A and thread B writes the value k + 1 back. In the end, the id k + 1 exists twice.<\/p>\n<p>The next example is quite surprising. Here is a small switch block:<\/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: #007788; font-weight: bold;\">unsigned<\/span> val;\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">if<\/span> (val <span style=\"color: #555555;\">&lt;<\/span> <span style=\"color: #ff6600;\">5<\/span>) {\r\n    <span style=\"color: #006699; font-weight: bold;\">switch<\/span> (val) {\r\n    <span style=\"color: #006699; font-weight: bold;\">case<\/span> <span style=\"color: #ff6600;\">0<\/span>: <span style=\"color: #0099ff; font-style: italic;\">\/\/ ...<\/span>\r\n    <span style=\"color: #006699; font-weight: bold;\">case<\/span> <span style=\"color: #ff6600;\">1<\/span>: <span style=\"color: #0099ff; font-style: italic;\">\/\/ ...<\/span>\r\n    <span style=\"color: #006699; font-weight: bold;\">case<\/span> <span style=\"color: #ff6600;\">2<\/span>: <span style=\"color: #0099ff; font-style: italic;\">\/\/ ...<\/span>\r\n    <span style=\"color: #006699; font-weight: bold;\">case<\/span> <span style=\"color: #ff6600;\">3<\/span>: <span style=\"color: #0099ff; font-style: italic;\">\/\/ ...<\/span>\r\n    <span style=\"color: #006699; font-weight: bold;\">case<\/span> <span style=\"color: #ff6600;\">4<\/span>: <span style=\"color: #0099ff; font-style: italic;\">\/\/ ...<\/span>\r\n    }\r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>The compiler will often implement the switch block as a jump table. Conceptually, it may look like this.<\/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: #006699; font-weight: bold;\">if<\/span> (val <span style=\"color: #555555;\">&lt;<\/span> <span style=\"color: #ff6600;\">5<\/span>){\r\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ (1)<\/span>\r\n    functions[val]();\r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>In this case, <span style=\"font-family: courier\\ new, courier;\">functions[3]()<\/span> stands for the functionality of the switch block if&nbsp;<span style=\"font-family: courier\\ new, courier;\">val<\/span>&nbsp;is equal to 3. Now it could happen, that another thread kicks in and changes the value at (1) so that it is outside the valid range. Of course, this is undefined behaviour.<\/p>\n<\/p>\n<h3><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rconc-data\">CP.3: Minimize explicit sharing of writable data<\/a><\/h3>\n<p>This is a straightforward to follow but a significant rule. If your share data, it should be constant.&nbsp;<\/p>\n<p>Now, you have only to solve the challenge that the shared data is initialized in a thread-safe way. C++11 supports a few ways to achieve this.<\/p>\n<ol>\n<li>Initialize your data before you start a thread. This is not due to C++11 but often quite easy to apply.<!-- HTML generated using hilite.me -->\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: #006699; font-weight: bold;\">const<\/span> <span style=\"color: #007788; font-weight: bold;\">int<\/span> val <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">2011<\/span>;\r\n<span style=\"color: #006699; font-weight: bold;\">thread<\/span> t1([<span style=\"color: #555555;\">&amp;<\/span>val]{ .... };\r\n<span style=\"color: #006699; font-weight: bold;\">thread<\/span> t2([<span style=\"color: #555555;\">&amp;<\/span>val]{ .... };\r\n<\/pre>\n<\/div>\n<\/li>\n<li>Use constant expressions because they are initialized at compile time. <!-- HTML generated using hilite.me -->\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\">constexpr <span style=\"color: #006699; font-weight: bold;\">auto<\/span> doub <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">5.1<\/span>;\r\n<\/pre>\n<\/div>\n<\/li>\n<li>Use the function <span style=\"font-family: courier\\ new, courier;\">std::call_once<\/span> in combination with the <span style=\"font-family: courier\\ new, courier;\"><span style=\"font-family: courier\\ new, courier;\">std::once_flag.<\/span><\/span> You can put the critical initialisation stuff into the function <span style=\"font-family: courier\\ new, courier;\">onlyOnceFunc<\/span>. The C++ runtime guarantees that this function runs exactly once successfully.<!-- HTML generated using hilite.me -->\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\">std<span style=\"color: #555555;\">::<\/span>once_flag onceFlag;\r\n<span style=\"color: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">do_once<\/span>(){\r\n  std<span style=\"color: #555555;\">::<\/span>call_once(onceFlag, [](){ std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"Important initialisation\"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl; });\r\n}\r\nstd<span style=\"color: #555555;\">::<\/span><span style=\"color: #006699; font-weight: bold;\">thread<\/span> t1(do_once);\r\nstd<span style=\"color: #555555;\">::<\/span><span style=\"color: #006699; font-weight: bold;\">thread<\/span> t2(do_once);\r\nstd<span style=\"color: #555555;\">::<\/span><span style=\"color: #006699; font-weight: bold;\">thread<\/span> t3(do_once);\r\nstd<span style=\"color: #555555;\">::<\/span><span style=\"color: #006699; font-weight: bold;\">thread<\/span> t4(do_once);\r\n<\/pre>\n<\/div>\n<\/li>\n<li>Use static variables with block scope because the C++11 runtime guarantees that they are initialized in a thread-safe way. <!-- HTML generated using hilite.me -->\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: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">func<\/span>(){\r\n  .... <br \/><span style=\"color: #006699; font-weight: bold;\">  static<\/span> <span style=\"color: #007788; font-weight: bold;\">int<\/span> val <span style=\"color: #ff6600;\">2011<\/span>; <br \/>  ....\r\n}\r\n<span style=\"color: #006699; font-weight: bold;\">thread<\/span> t5{ func() };\r\n<span style=\"color: #006699; font-weight: bold;\">thread<\/span> t6{ func() };\r\n<\/pre>\n<\/div>\n<\/li>\n<\/ol>\n<h3><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rconc-task\">CP.4: Think in terms of tasks, rather than threads<\/a><\/h3>\n<p>First of all. What is a task? A task is a term in C++11 that stands for two components: a promise and a future. Promise exists in three variations in C++: <span style=\"font-family: courier\\ new, courier;\">std::async, std::packaged_task,<\/span> and <span style=\"font-family: courier\\ new, courier;\">std::promise. <\/span>I have already written a few posts on <a href=\"https:\/\/www.modernescpp.com\/index.php\/tag\/tasks\">tasks<\/a>.<\/p>\n<p>A thread, a <span style=\"font-family: courier\\ new, courier;\">std::packaged_task,<\/span> or a <span style=\"font-family: courier\\ new, courier;\">std::promise<\/span>&nbsp;have in common that they are quite low-level; therefore, I will write about a <span style=\"font-family: courier\\ new, courier;\">std::async<\/span>.&nbsp;<\/p>\n<p>Here are a thread and a future and promise pair to calculate the sum of 3 + 4.<\/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;\">\/\/ thread<\/span>\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> res;\r\n<span style=\"color: #006699; font-weight: bold;\">thread<\/span> t([<span style=\"color: #555555;\">&amp;<\/span>]{ res <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">3<\/span> <span style=\"color: #555555;\">+<\/span> <span style=\"color: #ff6600;\">4<\/span>; });\r\nt.join();\r\ncout <span style=\"color: #555555;\">&lt;&lt;<\/span> res <span style=\"color: #555555;\">&lt;&lt;<\/span> endl;\r\n\r\n<span style=\"color: #0099ff; font-style: italic;\">\/\/ task<\/span>\r\n<span style=\"color: #006699; font-weight: bold;\">auto<\/span> fut <span style=\"color: #555555;\">=<\/span> async([]{ <span style=\"color: #006699; font-weight: bold;\">return<\/span> <span style=\"color: #ff6600;\">3<\/span> <span style=\"color: #555555;\">+<\/span> <span style=\"color: #ff6600;\">4<\/span>; });\r\ncout <span style=\"color: #555555;\">&lt;&lt;<\/span> fut.get() <span style=\"color: #555555;\">&lt;&lt;<\/span> endl;\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>What is the fundamental difference between a thread and a future and promise pair? <strong>A thread is about how something should be calculated; a task&nbsp;is about what should be calculated.<\/strong><\/p>\n<p>Let me be more specific.<\/p>\n<ul>\n<li>The thread uses the shared variable <span style=\"font-family: courier\\ new, courier;\">res<\/span> to provide its results. In contrast, the promise <span style=\"font-family: courier\\ new, courier;\">std::async<\/span> uses a secure data channel to communicate its result to the future <span style=\"font-family: courier\\ new, courier;\">fut.T<\/span>his means for the thread in particular that, you have to protect<span style=\"font-family: courier\\ new, courier;\"> res.<\/span><\/li>\n<li>In the case of a thread, you explicitly create a thread. This will not hold for the promise because you just specify what should be calculated.<\/li>\n<\/ul>\n<h3><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rconc-volatile\">CP.8: Don\u2019t try to use <code class=\"highlighter-rouge no-highlight\">volatile<\/code> for synchronization<\/a><\/h3>\n<p>If you want an atomic in Java or C# you declare it as <span style=\"font-family: courier\\ new, courier;\">volatile<\/span>. Relatively easy in C++, or? If you want to have an atomic in C++, use <span style=\"font-family: courier\\ new, courier;\">volatile<\/span>. Wrong. <span style=\"font-family: courier\\ new, courier;\">volatile<\/span> has no multithreading-semantic in C++. Atomics is called <span style=\"font-family: courier\\ new, courier;\">std::atomic<\/span> in C++11.<\/p>\n<p>Now, I&#8217;m curious: What does volatile mean in C++? <span style=\"font-family: courier\\ new, courier;\">volatile<\/span> is for special objects on which optimized read or write operations are not allowed.<\/p>\n<p><span style=\"font-family: courier\\ new, courier;\">volatile<\/span> is typically used in embedded programming to denote objects, which can change independently of the regular program flow. These are, for example, objects which represent an external device (memory-mapped I\/O). Because these objects can change independently of the regular program, their value will be written directly to the main memory. So there is no optimized storing in caches.<\/p>\n<h2>What&#8217;s next?<\/h2>\n<p>Correct multithreading is hard. This is why you should use each possible tool to validate your code. With the dynamic code analyzer <a href=\"https:\/\/clang.llvm.org\/docs\/ThreadSanitizer.html\">ThreadSanitizer<\/a> and the static code analyzer <a href=\"http:\/\/svr-pes20-cppmem.cl.cam.ac.uk\/cppmem\/\">CppMem<\/a> two tools should be in the toolbox of each serious multithreading programmer. In the<a href=\"https:\/\/goo.gl\/TmHfVh\"> next post<\/a>, you will see why.&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Writing multithreading programs is hard, even harder if the program should be correct. The rules of the C++ Core Guidelines guide you to writing correct programs. The rules of this post will deal with data races, sharing of data, tasks, and the infamous keyword volatile.<\/p>\n","protected":false},"author":21,"featured_media":5429,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[372],"tags":[446,457],"class_list":["post-5430","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-modern-c","tag-tasks","tag-volatile"],"_links":{"self":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5430","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=5430"}],"version-history":[{"count":1,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5430\/revisions"}],"predecessor-version":[{"id":6829,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5430\/revisions\/6829"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media\/5429"}],"wp:attachment":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media?parent=5430"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=5430"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=5430"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}