{"id":6074,"date":"2021-01-18T21:31:11","date_gmt":"2021-01-18T21:31:11","guid":{"rendered":"https:\/\/www.modernescpp.com\/index.php\/latches-in-c-20\/"},"modified":"2023-06-26T09:34:00","modified_gmt":"2023-06-26T09:34:00","slug":"latches-in-c-20","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/latches-in-c-20\/","title":{"rendered":"Latches in C++20"},"content":{"rendered":"<p>Latches and barriers are coordination types that enable some threads to wait until a counter becomes zero. You can use a <code>std::latch<\/code> only once, but you can use a <code>std::barrier<\/code> more than once. Today, I have a closer look at latches.<\/p>\n<p><!--more--><\/p>\n<p>&nbsp;<img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5199\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/02\/TimelineCpp20.png\" alt=\"TimelineCpp20\" width=\"650\" height=\"224\" style=\"display: block; margin-left: auto; margin-right: auto;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/02\/TimelineCpp20.png 894w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/02\/TimelineCpp20-300x103.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/02\/TimelineCpp20-768x265.png 768w\" sizes=\"auto, (max-width: 650px) 100vw, 650px\" \/><\/p>\n<p>Concurrent invocations of the member functions of a <code>std::latch<\/code> or a <code>std::barrier<\/code> are no data race. A data race is such a crucial term in concurrency that I want to write more words to it.<\/p>\n<h2>Data Race<\/h2>\n<p>A data race is a situation, in which at least two threads access a shared variable at the same time and at least one thread tries to modify the variable. If your program has a data race, it has undefined behavior. This means all outcomes are possible and therefore, reasoning about the program makes no sense anymore.<\/p>\n<p>Let me show you a program with a data race.<\/p>\n<p><!-- HTML generated using hilite.me --><\/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;\">\/\/ addMoney.cpp<\/span>\r\n\r\n<span style=\"color: #009999;\">#include &lt;functional&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<span style=\"color: #009999;\">#include &lt;vector&gt;<\/span>\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> Account{\r\n  <span style=\"color: #007788; font-weight: bold;\">int<\/span> balance{<span style=\"color: #ff6600;\">100<\/span>};                                                 <span style=\"color: #0099ff; font-style: italic;\">\/\/ (3)<\/span>               \r\n};\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">addMoney<\/span>(Account<span style=\"color: #555555;\">&amp;<\/span> to, <span style=\"color: #007788; font-weight: bold;\">int<\/span> amount){                             <span style=\"color: #0099ff; font-style: italic;\">\/\/ (2)<\/span> \r\n  to.balance <span style=\"color: #555555;\">+=<\/span> amount;                                             <span style=\"color: #0099ff; font-style: italic;\">\/\/ (1)<\/span>       \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> <span style=\"color: #cc3300;\">'\\n'<\/span>;\r\n\r\n  Account account;\r\n  \r\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> vecThreads(<span style=\"color: #ff6600;\">100<\/span>);\r\n                                           \r\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> vecThreads) thr <span style=\"color: #555555;\">=<\/span> std<span style=\"color: #555555;\">::<\/span><span style=\"color: #006699; font-weight: bold;\">thread<\/span>(addMoney, std<span style=\"color: #555555;\">::<\/span>ref(account), <span style=\"color: #ff6600;\">50<\/span>); <span style=\"color: #0099ff; font-style: italic;\"><\/span>\r\n  \r\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> vecThreads) thr.join();\r\n                                                 \r\n  std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"account.balance: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> account.balance <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;     <span style=\"color: #0099ff; font-style: italic;\">\/\/ (4)<\/span>\r\n  \r\n  std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\r\n\r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>100 threads adding 50 euros to the same account (1) using the function <code>addMoney<\/code> (2). The initial account is 100 (3). The crucial observation is that the writing to the account is done without synchronization. Therefore&nbsp;we have a data race and, consequently, undefined behavior. The final balance is between 5000 and 5100 euro (4).<\/p>\n<p>&nbsp;<img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5262\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/05\/addMoney.png\" alt=\"addMoney\" style=\"display: block; margin-left: auto; margin-right: auto;\" width=\"276\" height=\"321\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/05\/addMoney.png 276w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/05\/addMoney-258x300.png 258w\" sizes=\"auto, (max-width: 276px) 100vw, 276px\" \/><\/p>\n<p>What is happening? Why are a few additions missing? The update process <code>to.balance <span style=\"color: #555555;\">+=<\/span> amount; <\/code>in line (1) is a so-called read-modify-write operation. As such, first, the old value of <code>to.balance<\/code> is read, then it is updated, and finally is written. What may happen under the hood is the following. I use numbers to make my argumentation more obvious<\/p>\n<ul>\n<li>Thread A reads the value 500 euro and then Thread B kicks in.<\/li>\n<li>Thread B read also the value 500 euro, adds 50 euro to it, and updates <code>to.balance<\/code> to 550 euro.<\/li>\n<li>Now Thread A finished its execution by adding 50 euro to <code>to.balance<\/code> and also writes 550 euro.<\/li>\n<li>Essential the value 550 euro is written twice and instead of two additions of 50 euro, we only observe one.<\/li>\n<li>This means, that one modification is lost and we get the wrong final sum.<\/li>\n<\/ul>\n<p>First, there are two questions to answer before I present <code>std::latch<\/code> and <code>std::barrier<\/code> in detail.<\/p>\n<\/p>\n<h2>Two Questions<code><br \/><\/code><\/h2>\n<ol>\n<li><strong>What is the difference between these two mechanisms to coordinate threads?<\/strong> You can use a <code>std::latch<\/code> only once, but you can use a <code>std::barrier<\/code> more than once. A <code>std::latch<\/code> is useful for managing one task by multiple threads; a<code> std::barrier<\/code> is helpful for managing repeated tasks by multiple threads. Additionally, a <code>std::barrier<\/code> enables you to execute a function in the so-called completion step. The completion step is the state when the counter becomes zero.<\/li>\n<li><strong>What use cases do latches and barriers support that cannot be done in C++11 with futures, threads, or condition variables combined with locks?<\/strong> Latches and barriers address no new use cases, but they are a lot easier to use. They are also more performant because they often use a&nbsp;<a href=\"https:\/\/en.wikipedia.org\/wiki\/Non-blocking_algorithm\">lock-free <\/a>mechanism internally.<\/li>\n<\/ol>\n<p>Let me continue my post with the simpler data type of both.<\/p>\n<h2><code>std::latch<\/code><\/h2>\n<p>Now, let us have a closer look at the interface of a <code>std::latch<\/code>.<\/p>\n<p>&nbsp;<img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-6071\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/01\/memberFunctionsLatch.png\" alt=\"memberFunctionsLatch\" width=\"600\" height=\"161\" style=\"display: block; margin-left: auto; margin-right: auto;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/01\/memberFunctionsLatch.png 826w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/01\/memberFunctionsLatch-300x81.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/01\/memberFunctionsLatch-768x206.png 768w\" sizes=\"auto, (max-width: 600px) 100vw, 600px\" \/><\/p>\n<p>The default value for <code>upd<\/code> is <code>1<\/code>. When <code>upd<\/code> is greater than the counter or negative, the behaviour is undefined. The call <code>lat.try_wait()<\/code> does never wait as its name suggests.<\/p>\n<p>The following program <code>bossWorkers.cpp<\/code> uses two <code>std::latch<\/code> to build a boss-workers workflow. I synchronized the output to <code>std::cout<\/code> use the function <code>synchronizedOut<\/code> (1). This synchronization makes it easier to follow the workflow.<\/p>\n<p>&nbsp;<\/p>\n<p><!-- HTML generated using hilite.me --><\/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;\">\/\/ bossWorkers.cpp<\/span>\r\n\r\n<span style=\"color: #009999;\">#include &lt;iostream&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;mutex&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;latch&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;thread&gt;<\/span>\r\n\r\nstd<span style=\"color: #555555;\">::<\/span>latch workDone(<span style=\"color: #ff6600;\">6<\/span>);\r\nstd<span style=\"color: #555555;\">::<\/span>latch goHome(<span style=\"color: #ff6600;\">1<\/span>);                                       <span style=\"color: #0099ff; font-style: italic;\">\/\/ (4)<\/span>\r\n\r\nstd<span style=\"color: #555555;\">::<\/span>mutex coutMutex;\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">synchronizedOut<\/span>(<span style=\"color: #006699; font-weight: bold;\">const<\/span> std<span style=\"color: #555555;\">::<\/span>string s) {                <span style=\"color: #0099ff; font-style: italic;\">\/\/ (1)<\/span>\r\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> lo(coutMutex);\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> s;\r\n}\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">Worker<\/span> {\r\n <span style=\"color: #9999ff;\">public:<\/span>\r\n     Worker(std<span style=\"color: #555555;\">::<\/span>string n)<span style=\"color: #555555;\">:<\/span> name(n) { };\r\n  \r\n      <span style=\"color: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">operator<\/span>() (){\r\n          <span style=\"color: #0099ff; font-style: italic;\">\/\/ notify the boss when work is done<\/span>\r\n          synchronizedOut(name <span style=\"color: #555555;\">+<\/span> <span style=\"color: #cc3300;\">\": \"<\/span> <span style=\"color: #555555;\">+<\/span> <span style=\"color: #cc3300;\">\"Work done!<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>);\r\n          workDone.count_down();                          <span style=\"color: #0099ff; font-style: italic;\">\/\/ (2)<\/span>\r\n\r\n          <span style=\"color: #0099ff; font-style: italic;\">\/\/ waiting before going home<\/span>\r\n          goHome.wait();                                  <span style=\"color: #0099ff; font-style: italic;\">\/\/ (5)<\/span>\r\n          synchronizedOut(name <span style=\"color: #555555;\">+<\/span> <span style=\"color: #cc3300;\">\": \"<\/span> <span style=\"color: #555555;\">+<\/span> <span style=\"color: #cc3300;\">\"Good bye!<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>);\r\n      }\r\n <span style=\"color: #9999ff;\">private:<\/span>\r\n    std<span style=\"color: #555555;\">::<\/span>string name;\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> <span style=\"color: #cc3300;\">'\\n'<\/span>;\r\n\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"BOSS: START WORKING! \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\r\n  \r\n    Worker herb(<span style=\"color: #cc3300;\">\"  Herb\"<\/span>);\r\n    std<span style=\"color: #555555;\">::<\/span><span style=\"color: #006699; font-weight: bold;\">thread<\/span> herbWork(herb);\r\n  \r\n    Worker scott(<span style=\"color: #cc3300;\">\"    Scott\"<\/span>);\r\n    std<span style=\"color: #555555;\">::<\/span><span style=\"color: #006699; font-weight: bold;\">thread<\/span> scottWork(scott);\r\n  \r\n    Worker bjarne(<span style=\"color: #cc3300;\">\"      Bjarne\"<\/span>);\r\n    std<span style=\"color: #555555;\">::<\/span><span style=\"color: #006699; font-weight: bold;\">thread<\/span> bjarneWork(bjarne);\r\n  \r\n    Worker andrei(<span style=\"color: #cc3300;\">\"        Andrei\"<\/span>);\r\n    std<span style=\"color: #555555;\">::<\/span><span style=\"color: #006699; font-weight: bold;\">thread<\/span> andreiWork(andrei);\r\n  \r\n    Worker andrew(<span style=\"color: #cc3300;\">\"          Andrew\"<\/span>);\r\n    std<span style=\"color: #555555;\">::<\/span><span style=\"color: #006699; font-weight: bold;\">thread<\/span> andrewWork(andrew);\r\n  \r\n    Worker david(<span style=\"color: #cc3300;\">\"            David\"<\/span>);\r\n    std<span style=\"color: #555555;\">::<\/span><span style=\"color: #006699; font-weight: bold;\">thread<\/span> davidWork(david);\r\n    \r\n    workDone.wait();                                       <span style=\"color: #0099ff; font-style: italic;\">\/\/ (3)<\/span>\r\n\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\r\n\r\n    goHome.count_down();\r\n\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"BOSS: GO HOME!\"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\r\n\r\n    herbWork.join();\r\n    scottWork.join();\r\n    bjarneWork.join();\r\n    andreiWork.join();\r\n    andrewWork.join();\r\n    davidWork.join();\r\n  \r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>The idea of the workflow is straightforward. The six workers <code>herb<\/code>, <code>scott<\/code>, <code>bjarne<\/code>, <code>andrei<\/code>, <code>andrew<\/code>, and <code>david<\/code> in the <code>main<\/code>-program have to fulfill their job. When they finished their job, they count down the <code>std::latch workDone<\/code> (2). The boss (<code>main<\/code>-thread) is blocked in line (3) until the counter becomes 0. When the counter is 0, the boss uses the second <code>std::latch goHome<\/code> to signal its workers to go home. In this case, the initial counter is <code>1<\/code> (4). The call g<code>oHome.wait<\/code> (5) blocks until the counter becomes 0.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-6072\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/01\/bossWorkers.png\" alt=\"bossWorkers\" width=\"300\" height=\"314\" style=\"display: block; margin-left: auto; margin-right: auto;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/01\/bossWorkers.png 348w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/01\/bossWorkers-287x300.png 287w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/p>\n<p>When you think about this workflow, you may notice that it can be performed without a boss. Here is the modern variant:<\/p>\n<p>&nbsp;<\/p>\n<p><!-- HTML generated using hilite.me --><\/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;\">\/\/ workers.cpp<\/span>\r\n\r\n<span style=\"color: #009999;\">#include &lt;iostream&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;latch&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;mutex&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;thread&gt;<\/span>\r\n\r\nstd<span style=\"color: #555555;\">::<\/span>latch workDone(<span style=\"color: #ff6600;\">6<\/span>);\r\nstd<span style=\"color: #555555;\">::<\/span>mutex coutMutex;\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">synchronizedOut<\/span>(<span style=\"color: #006699; font-weight: bold;\">const<\/span> std<span style=\"color: #555555;\">::<\/span>string<span style=\"color: #555555;\">&amp;<\/span> s) {\r\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> lo(coutMutex);\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> s;\r\n}\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">Worker<\/span> {\r\n <span style=\"color: #9999ff;\">public:<\/span>\r\n    Worker(std<span style=\"color: #555555;\">::<\/span>string n)<span style=\"color: #555555;\">:<\/span> name(n) { };\r\n  \r\n    <span style=\"color: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">operator<\/span>() () {\r\n        synchronizedOut(name <span style=\"color: #555555;\">+<\/span> <span style=\"color: #cc3300;\">\": \"<\/span> <span style=\"color: #555555;\">+<\/span> <span style=\"color: #cc3300;\">\"Work done!<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>);\r\n        workDone.arrive_and_wait();  <span style=\"color: #0099ff; font-style: italic;\">\/\/ wait until all work is done  (1)<\/span>\r\n        synchronizedOut(name <span style=\"color: #555555;\">+<\/span> <span style=\"color: #cc3300;\">\": \"<\/span> <span style=\"color: #555555;\">+<\/span> <span style=\"color: #cc3300;\">\"See you tomorrow!<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>);\r\n    }\r\n <span style=\"color: #9999ff;\">private:<\/span>\r\n    std<span style=\"color: #555555;\">::<\/span>string name;\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> <span style=\"color: #cc3300;\">'\\n'<\/span>;\r\n\r\n    Worker herb(<span style=\"color: #cc3300;\">\"  Herb\"<\/span>);\r\n    std<span style=\"color: #555555;\">::<\/span><span style=\"color: #006699; font-weight: bold;\">thread<\/span> herbWork(herb);\r\n  \r\n    Worker scott(<span style=\"color: #cc3300;\">\"    Scott\"<\/span>);\r\n    std<span style=\"color: #555555;\">::<\/span><span style=\"color: #006699; font-weight: bold;\">thread<\/span> scottWork(scott);\r\n  \r\n    Worker bjarne(<span style=\"color: #cc3300;\">\"      Bjarne\"<\/span>);\r\n    std<span style=\"color: #555555;\">::<\/span><span style=\"color: #006699; font-weight: bold;\">thread<\/span> bjarneWork(bjarne);\r\n  \r\n    Worker andrei(<span style=\"color: #cc3300;\">\"        Andrei\"<\/span>);\r\n    std<span style=\"color: #555555;\">::<\/span><span style=\"color: #006699; font-weight: bold;\">thread<\/span> andreiWork(andrei);\r\n  \r\n    Worker andrew(<span style=\"color: #cc3300;\">\"          Andrew\"<\/span>);\r\n    std<span style=\"color: #555555;\">::<\/span><span style=\"color: #006699; font-weight: bold;\">thread<\/span> andrewWork(andrew);\r\n  \r\n    Worker david(<span style=\"color: #cc3300;\">\"            David\"<\/span>);\r\n    std<span style=\"color: #555555;\">::<\/span><span style=\"color: #006699; font-weight: bold;\">thread<\/span> davidWork(david);\r\n\r\n    herbWork.join();\r\n    scottWork.join();\r\n    bjarneWork.join();\r\n    andreiWork.join();\r\n    andrewWork.join();\r\n    davidWork.join();\r\n  \r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>There is not much to add to this simplified workflow. The call <code>workDone.arrive_and_wait(1)<\/code> (1) is equivalent to the calls <code>count_down(upd); wait();<\/code>. This means the workers coordinate themself and the boss is no longer necessary such as in the previous program <code>bossWorkers.cpp<\/code>.<\/p>\n<h2><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-6073\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/01\/workers.png\" alt=\"workers\" style=\"display: block; margin-left: auto; margin-right: auto;\" width=\"453\" height=\"318\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/01\/workers.png 453w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/01\/workers-300x211.png 300w\" sizes=\"auto, (max-width: 453px) 100vw, 453px\" \/><\/h2>\n<h2>What&#8217;s next?<\/h2>\n<p>A <code>std::barrier <\/code>is quite similar to a <code>std::latch<\/code>. <code>std::barrier<\/code>&#8216;s strength is it to perform a job more than once. In my<a href=\"https:\/\/www.modernescpp.com\/index.php\/barriers-in-c-20\"> next post<\/a>, I will have a closer look at barriers.<\/p>\n<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Latches and barriers are coordination types that enable some threads to wait until a counter becomes zero. You can use a std::latch only once, but you can use a std::barrier more than once. Today, I have a closer look at latches.<\/p>\n","protected":false},"author":21,"featured_media":5199,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[375],"tags":[450],"class_list":["post-6074","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-c-20","tag-latches"],"_links":{"self":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/6074","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=6074"}],"version-history":[{"count":1,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/6074\/revisions"}],"predecessor-version":[{"id":6716,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/6074\/revisions\/6716"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media\/5199"}],"wp:attachment":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media?parent=6074"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=6074"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=6074"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}