{"id":5202,"date":"2017-02-27T17:04:26","date_gmt":"2017-02-27T17:04:26","guid":{"rendered":"https:\/\/www.modernescpp.com\/index.php\/coroutines\/"},"modified":"2023-06-26T12:21:06","modified_gmt":"2023-06-26T12:21:06","slug":"coroutines","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/coroutines\/","title":{"rendered":"Coroutines"},"content":{"rendered":"<p>Coroutines are functions that can suspend and resume their execution while keeping their state. The evolution in C++20 goes one step further.<\/p>\n<p><!--more--><\/p>\n<p>What I present in this post as a new idea in C++20 is quite old. Melvin Conway coins the term coroutines. He used it in his publication of compiler construction in 1963. <a href=\"https:\/\/en.wikipedia.org\/wiki\/Donald_Knuth\">Donald Knuth<\/a> called procedures a particular case of coroutines. Sometimes, it just takes a bit longer.<\/p>\n<p>Although I know coroutines from Python, it was quite challenging for me to understand the new concept in C++20. Hence, before I dive into the details, here is the first contact.<\/p>\n<\/p>\n<h2>A first contact<\/h2>\n<p>With the new keywords <span style=\"font-family: courier new,courier;\">co_await<\/span> and <span style=\"font-family: courier new,courier;\">co_yield, <\/span>C++20 will extend the concept of a function.<\/p>\n<p>Thanks to&nbsp; <strong><span style=\"font-family: courier new,courier;\">co_await expression<\/span><\/strong>, it is possible to suspend and resume the execution of the <span style=\"font-family: courier new,courier;\">expression<\/span>. If you use <span style=\"font-family: courier new,courier;\">co_await expression<\/span> in a function <span style=\"font-family: courier new,courier;\">func<\/span>, the call&nbsp; <span style=\"font-family: courier new,courier;\">auto getResult = func()<\/span> has not to be blocked, if the function result is unavailable. Instead of resource-consuming blocking, you have resource-friendly waiting.<\/p>\n<p><span style=\"font-family: courier new,courier;\"><strong>co_yield expression<\/strong><\/span> enables it to write a generator function. The generator function returns on request each time a new value is. A generator function is a data stream from which you can pick values. The data stream can be infinite; therefore, we are at the center of <a href=\"https:\/\/www.modernescpp.com\/index.php\/recursion-list-manipulation-and-lazy-evaluation\">lazy evaluation<\/a> with C++.<\/p>\n<h3>A simple example<\/h3>\n<p>The program is as simple as possible. The function <span style=\"font-family: courier new,courier;\">getNumbers<\/span> returns all integers from <span style=\"font-family: courier new,courier;\">begin<\/span> to <span style=\"font-family: courier new,courier;\">end<\/span> incremented by <span style=\"font-family: courier new,courier;\">inc<\/span>. <span style=\"font-family: courier new,courier;\">begin<\/span> has to be smaller than <span style=\"font-family: courier new,courier;\">end<\/span>, and <span style=\"font-family: courier new,courier;\">inc<\/span> has to be positive.<\/p>\n<div style=\"background: #ffffff none repeat scroll 0% 0%; overflow: auto; width: auto; border-width: 0.1em 0.1em 0.1em 0.8em;\">\n<table>\n<tbody>\n<tr>\n<td>\n<pre style=\"margin: 0px; line-height: 125%;\"> 1\r\n 2\r\n 3\r\n 4\r\n 5\r\n 6\r\n 7\r\n 8\r\n 9\r\n10\r\n11\r\n12\r\n13\r\n14\r\n15\r\n16\r\n17\r\n18\r\n19\r\n20\r\n21\r\n22\r\n23\r\n24\r\n25\r\n26\r\n27\r\n28\r\n29\r\n30\r\n31<\/pre>\n<\/td>\n<td>\n<pre style=\"margin: 0px; line-height: 125%;\"><span style=\"color: #888888;\">\/\/ greedyGenerator.cpp<\/span>\r\n\r\n<span style=\"color: #557799;\">#include &lt;iostream&gt;<\/span>\r\n<span style=\"color: #557799;\">#include &lt;vector&gt;<\/span>\r\n\r\nstd<span style=\"color: #333333;\">::<\/span>vector<span style=\"color: #333333;\">&lt;<\/span><span style=\"color: #333399; font-weight: bold;\">int<\/span><span style=\"color: #333333;\">&gt;<\/span> getNumbers(<span style=\"color: #333399; font-weight: bold;\">int<\/span> begin, <span style=\"color: #333399; font-weight: bold;\">int<\/span> end, <span style=\"color: #333399; font-weight: bold;\">int<\/span> inc<span style=\"color: #333333;\">=<\/span> <span style=\"color: #0000dd; font-weight: bold;\">1<\/span>){\r\n  \r\n  std<span style=\"color: #333333;\">::<\/span>vector<span style=\"color: #333333;\">&lt;<\/span><span style=\"color: #333399; font-weight: bold;\">int<\/span><span style=\"color: #333333;\">&gt;<\/span> numbers;\r\n  <span style=\"color: #008800; font-weight: bold;\">for<\/span> (<span style=\"color: #333399; font-weight: bold;\">int<\/span> i<span style=\"color: #333333;\">=<\/span> begin; i <span style=\"color: #333333;\">&lt;<\/span> end; i <span style=\"color: #333333;\">+=<\/span> inc){\r\n    numbers.push_back(i);\r\n  }\r\n  \r\n  <span style=\"color: #008800; font-weight: bold;\">return<\/span> numbers;\r\n  \r\n}\r\n\r\n<span style=\"color: #333399; font-weight: bold;\">int<\/span> main(){\r\n\r\n  std<span style=\"color: #333333;\">::<\/span>cout <span style=\"color: #333333;\">&lt;&lt;<\/span> std<span style=\"color: #333333;\">::<\/span>endl;\r\n\r\n  <span style=\"color: #008800; font-weight: bold;\">auto<\/span> numbers<span style=\"color: #333333;\">=<\/span> getNumbers(<span style=\"color: #333333;\">-<\/span><span style=\"color: #0000dd; font-weight: bold;\">10<\/span>, <span style=\"color: #0000dd; font-weight: bold;\">11<\/span>);\r\n  \r\n  <span style=\"color: #008800; font-weight: bold;\">for<\/span> (<span style=\"color: #008800; font-weight: bold;\">auto<\/span> n<span style=\"color: #333333;\">:<\/span> numbers) std<span style=\"color: #333333;\">::<\/span>cout <span style=\"color: #333333;\">&lt;&lt;<\/span> n <span style=\"color: #333333;\">&lt;&lt;<\/span> <span style=\"background-color: #fff0f0;\">\" \"<\/span>;\r\n  \r\n  std<span style=\"color: #333333;\">::<\/span>cout <span style=\"color: #333333;\">&lt;&lt;<\/span> <span style=\"background-color: #fff0f0;\">\"<\/span><span style=\"color: #666666; font-weight: bold; background-color: #fff0f0;\">\\n\\n<\/span><span style=\"background-color: #fff0f0;\">\"<\/span>;\r\n\r\n  <span style=\"color: #008800; font-weight: bold;\">for<\/span> (<span style=\"color: #008800; font-weight: bold;\">auto<\/span> n<span style=\"color: #333333;\">:<\/span> getNumbers(<span style=\"color: #0000dd; font-weight: bold;\">0<\/span>,<span style=\"color: #0000dd; font-weight: bold;\">101<\/span>,<span style=\"color: #0000dd; font-weight: bold;\">5<\/span>)) std<span style=\"color: #333333;\">::<\/span>cout <span style=\"color: #333333;\">&lt;&lt;<\/span> n <span style=\"color: #333333;\">&lt;&lt;<\/span> <span style=\"background-color: #fff0f0;\">\" \"<\/span>;\r\n\r\n  std<span style=\"color: #333333;\">::<\/span>cout <span style=\"color: #333333;\">&lt;&lt;<\/span> <span style=\"background-color: #fff0f0;\">\"<\/span><span style=\"color: #666666; font-weight: bold; background-color: #fff0f0;\">\\n\\n<\/span><span style=\"background-color: #fff0f0;\">\"<\/span>;\r\n\r\n}\r\n<\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p>&nbsp;<\/p>\n<p>Of course, I reinvented the wheel with <span style=\"font-family: courier;\">getNumbers<\/span> because since C++11, that job can be done with&nbsp; <a href=\"http:\/\/en.cppreference.com\/w\/cpp\/algorithm\/iota\"><span style=\"font-family: courier new,courier;\">std::iota<\/span><\/a>.<\/p>\n<p>For completeness, here is the output.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5201\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/02\/greedyGenerator.png\" alt=\"greedyGenerator\" width=\"674\" height=\"174\" style=\"margin: 15px;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/02\/greedyGenerator.png 674w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/02\/greedyGenerator-300x77.png 300w\" sizes=\"auto, (max-width: 674px) 100vw, 674px\" \/><\/p>\n<p>Two observations about the program are essential. On the other hand, the vector <span style=\"font-family: courier;\">numbers<\/span> in line 8 always get all values. That even holds if I&#8217;m only interested in the first five elements of a vector with 1000 elements. On the other hand, it&#8217;s quite easy to transform the function <span style=\"font-family: courier;\">getNumbers<\/span> into a generator.<\/p>\n<div style=\"background: #ffffff none repeat scroll 0% 0%; overflow: auto; width: auto; border-width: 0.1em 0.1em 0.1em 0.8em;\">\n<table>\n<tbody>\n<tr>\n<td>\n<pre style=\"margin: 0px; line-height: 125%;\"> 1\r\n 2\r\n 3\r\n 4\r\n 5\r\n 6\r\n 7\r\n 8\r\n 9\r\n10\r\n11\r\n12\r\n13\r\n14\r\n15\r\n16\r\n17\r\n18\r\n19\r\n20\r\n21\r\n22\r\n23\r\n24\r\n25\r\n26\r\n27\r\n28<\/pre>\n<\/td>\n<td>\n<pre style=\"margin: 0px; line-height: 125%;\"><span style=\"color: #888888;\">\/\/ lazyGenerator.cpp<\/span>\r\n\r\n<span style=\"color: #557799;\">#include &lt;iostream&gt;<\/span>\r\n<span style=\"color: #557799;\">#include &lt;vector&gt;<\/span>\r\n\r\ngenerator<span style=\"color: #333333;\">&lt;<\/span><span style=\"color: #333399; font-weight: bold;\">int<\/span><span style=\"color: #333333;\">&gt;<\/span> generatorForNumbers(<span style=\"color: #333399; font-weight: bold;\">int<\/span> begin, <span style=\"color: #333399; font-weight: bold;\">int<\/span> inc<span style=\"color: #333333;\">=<\/span> <span style=\"color: #0000dd; font-weight: bold;\">1<\/span>){\r\n  \r\n  <span style=\"color: #008800; font-weight: bold;\">for<\/span> (<span style=\"color: #333399; font-weight: bold;\">int<\/span> i<span style=\"color: #333333;\">=<\/span> begin;; i <span style=\"color: #333333;\">+=<\/span> inc){\r\n    co_yield i;\r\n  }\r\n  \r\n}\r\n\r\n<span style=\"color: #333399; font-weight: bold;\">int<\/span> main(){\r\n\r\n  std<span style=\"color: #333333;\">::<\/span>cout <span style=\"color: #333333;\">&lt;&lt;<\/span> std<span style=\"color: #333333;\">::<\/span>endl;\r\n\r\n  <span style=\"color: #008800; font-weight: bold;\">auto<\/span> numbers<span style=\"color: #333333;\">=<\/span> generatorForNumbers(<span style=\"color: #333333;\">-<\/span><span style=\"color: #0000dd; font-weight: bold;\">10<\/span>);\r\n  \r\n  <span style=\"color: #008800; font-weight: bold;\">for<\/span> (<span style=\"color: #008800; font-weight: bold;\"><\/span><span style=\"color: #333333;\">int i= 1; i &lt;= 20; ++i<\/span>) std<span style=\"color: #333333;\">::<\/span>cout <span style=\"color: #333333;\">&lt;&lt;<\/span> numbers <span style=\"color: #333333;\">&lt;&lt;<\/span> <span style=\"background-color: #fff0f0;\">\" \"<\/span>;\r\n  \r\n  std<span style=\"color: #333333;\">::<\/span>cout <span style=\"color: #333333;\">&lt;&lt;<\/span> <span style=\"background-color: #fff0f0;\">\"<\/span><span style=\"color: #666666; font-weight: bold; background-color: #fff0f0;\">\\n\\n<\/span><span style=\"background-color: #fff0f0;\">\"<\/span>;\r\n\r\n  <span style=\"color: #008800; font-weight: bold;\">for<\/span> (<span style=\"color: #008800; font-weight: bold;\">auto<\/span> n<span style=\"color: #333333;\">:<\/span> generatorForNumbers(<span style=\"color: #0000dd; font-weight: bold;\">0<\/span>, <span style=\"color: #0000dd; font-weight: bold;\">5<\/span>)) std<span style=\"color: #333333;\">::<\/span>cout <span style=\"color: #333333;\">&lt;&lt;<\/span> n <span style=\"color: #333333;\">&lt;&lt;<\/span> <span style=\"background-color: #fff0f0;\">\" \"<\/span>;\r\n\r\n  std<span style=\"color: #333333;\">::<\/span>cout <span style=\"color: #333333;\">&lt;&lt;<\/span> <span style=\"background-color: #fff0f0;\">\"<\/span><span style=\"color: #666666; font-weight: bold; background-color: #fff0f0;\">\\n\\n<\/span><span style=\"background-color: #fff0f0;\">\"<\/span>;\r\n\r\n}\r\n<\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p>&nbsp;<\/p>\n<p>While the function <span style=\"font-family: Courier New,Courier,monospace;\">getNumbers <\/span>in the file <span style=\"font-family: Courier New,Courier,monospace;\">greedyGenerator.cpp<\/span> returns a <span style=\"font-family: Courier New,Courier,monospace;\">std::vector&lt;int&gt;<\/span>, the coroutine <span style=\"font-family: Courier New,Courier,monospace;\">generatorForNumbers<\/span> in <span style=\"font-family: Courier New,Courier,monospace;\">lazyGenerator.cpp<\/span> returns a generator. The generator <span style=\"font-family: Courier New,Courier,monospace;\">numbers <\/span>in line 18 or <span style=\"font-family: Courier New,Courier,monospace;\">generatorForNumbers(0, 5)<\/span> in line 24 return on request a new number. The range-based for-loop triggers the query. To be precise. The query of the coroutine returns the value <span style=\"font-family: Courier New,Courier,monospace;\">i <\/span>via <span style=\"font-family: Courier New,Courier,monospace;\">co_yield i<\/span> and immediately suspends its execution. If a new value is requested, the coroutine resumes its execution precisely at that place.<\/p>\n<p>The expression <span style=\"font-family: courier;\">getForNumber(0, 5)<\/span> in line 24 may look slightly weird. This is a just-in-place usage of a generator.<\/p>\n<p>I want to stress one point explicitly. The coroutine <span style=\"font-family: courier;\">generatorForNumbers<\/span> creates an infinite data stream because the for-loop in line 8 has no end condition. That is no problem if I only ask for a finite number of values, such as in line 20. That will not hold for line 24. There is no end condition.<\/p>\n<p>As promised. Here are the details of the coroutines. I will answer the following questions:<\/p>\n<ul>\n<li>What are the typical use cases for coroutines?<\/li>\n<li>What are the concepts used by coroutines?<\/li>\n<li>What are the design goals for coroutines?<\/li>\n<li>How does a function become a coroutine?<\/li>\n<li>What are the characteristics of the two new keywords <span style=\"font-family: courier new,courier;\">co_await<\/span> and <span style=\"font-family: courier new,courier;\">co_yield<\/span>?<\/li>\n<\/ul>\n<h2>More details<\/h2>\n<p>At first, the simpler questions?<\/p>\n<h3>What are the typical use cases for coroutines?<\/h3>\n<p>Coroutines are the natural way to write <a href=\"https:\/\/en.wikipedia.org\/wiki\/Event-driven_programming\">event-driven applications<\/a>. This can be simulations, games, servers, user interfaces, or algorithms. Coroutines are typically used for <a href=\"https:\/\/de.wikipedia.org\/wiki\/Multitasking\">cooperative multitasking<\/a>. The key to cooperative multitasking is that each task takes as much time as it needs. That is in contrast to pre-emptive multitasking. Here we have a scheduler that decides how long each task gets the CPU.<\/p>\n<p>There are different versions of coroutines.<\/p>\n<h3>What are the concepts used by coroutines?<\/h3>\n<p>Coroutines in C++20 are asymmetric, first-class, and stackless.<\/p>\n<p>The workflow of an asymmetric coroutine goes back to the caller. That must not hold for a symmetric coroutine. An asymmetric coroutine can delegate its workflow to another coroutine.<\/p>\n<p>First-class coroutines are similar to <a href=\"https:\/\/www.modernescpp.com\/index.php\/first-class-functions\">First-Class Functions<\/a> because coroutines behave like data. That means you can use them as an argument, return a function&#8217;s value, or store them in a variable.<\/p>\n<p>A stackless coroutine enables it to suspend and resume the top-level coroutine. But this coroutine can not invoke another coroutine.<\/p>\n<p>Proposal <a href=\"https:\/\/isocpp.org\/files\/papers\/N4402.pdf\">n4402 <\/a>describes the design goals of coroutines.<\/p>\n<h3>What are the design goals for coroutines?<\/h3>\n<p>Coroutines should be<\/p>\n<ul>\n<li>Highly scalable (to billions of concurrent coroutines).<\/li>\n<li>Highly efficient resume and suspend operations comparable in cost to a function call overhead.<\/li>\n<li>Seamless interaction with existing facilities with no overhead.<\/li>\n<li>Open-ended coroutine machinery allows library designers to develop coroutine libraries exposing various high-level semantics, such as generators, goroutines, tasks, and more.<\/li>\n<li>Usable in environments where exceptions are forbidden or not available<\/li>\n<\/ul>\n<p>There are four reasons a function becomes a coroutine.<\/p>\n<h3>How does a function become a coroutine?<\/h3>\n<p>A function becomes a coroutine if it uses<\/p>\n<ul>\n<li><span style=\"font-family: courier new,courier;\">co_return<\/span>, or<\/li>\n<li><span style=\"font-family: courier new,courier;\">co_await<\/span>, or<\/li>\n<li><span style=\"font-family: courier new,courier;\">co_yield<\/span>, or<\/li>\n<li>a <span style=\"font-family: courier new,courier;\">co_await<\/span> expression in a range-based for-loop.<\/li>\n<\/ul>\n<p>The answer to this question was from proposal <a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2016\/n4628.pdf\">n4628<\/a>.<\/p>\n<p>Finally, I come to the new keywords&nbsp; <span style=\"font-family: courier new,courier;\">co_return<\/span>, <span style=\"font-family: courier new,courier;\">co_yield<\/span>, and <span style=\"font-family: courier new,courier;\">co_await<\/span>.<span style=\"font-family: courier new,courier;\"><\/span><\/p>\n<h3>co_return, co_yield and co_await<\/h3>\n<p><strong><span style=\"font-family: courier new,courier;\">co_return:<\/span><\/strong> A coroutine returns from its function body with <span style=\"font-family: courier new,courier;\">co_return<\/span>.<\/p>\n<p><span style=\"font-family: courier new,courier;\"><strong>co_yield:<\/strong><\/span> Thanks to <span style=\"font-family: courier new,courier;\">co_yield<\/span>,&nbsp; you can implement a generator. Therefore, you can create a generator&nbsp; (<span style=\"font-family: courier new,courier;\">lazyGenerator.cpp<\/span>) generating an infinite data stream from which you can successively query values. The return type of the generator <span style=\"font-family: courier new,courier;\"><span style=\"color: #000000;\">generator<span style=\"color: #333333;\">&lt;<\/span><span style=\"color: #000000;\">int<\/span><span style=\"color: #333333;\">&gt;<\/span> <span style=\"color: #000000;\">generatorForNumbers(int<\/span> begin, int inc = 1<span style=\"font-weight: bold;\"><\/span><\/span>) <\/span>is, in this case, <span style=\"font-family: courier new,courier;\">generator&lt;int&gt;. generator&lt;int&gt; <\/span>internally holds a particular <a href=\"https:\/\/www.modernescpp.com\/index.php\/promise-and-future\">promise<\/a> <span style=\"font-family: Courier New,Courier,monospace;\">p<\/span> such that a call <span style=\"font-family: courier new,courier;\">co_yield i <\/span>is equivalent to a call<span style=\"font-family: courier new,courier;\"> co_await p.yield_value(i).<\/span> <span style=\"font-family: courier new,courier;\"><span style=\"font-family: courier new,courier;\">co_yield i <\/span><\/span>can be arbitrarily often called.&nbsp; Immediately after the call, the execution of the coroutine will be suspended.&nbsp;<span style=\"font-family: courier new,courier;\"> <\/span><\/p>\n<p><strong>co<span style=\"font-family: courier new,courier;\">_await<\/span><\/strong>: <span style=\"font-family: courier new,courier;\">co_await<\/span> eventually causes the execution of the coroutine to be suspended and resumed. The expression <span style=\"font-family: courier;\">exp<\/span> in <span style=\"font-family: courier;\">co_await exp<\/span> has to be a so-called awaitable expression. <span style=\"font-family: courier;\">exp <\/span>has to implement a specific interface. This interface consists of three functions<em><\/em> <span style=\"font-family: courier new,courier;\">e.await_ready<\/span>, <span style=\"font-family: courier new,courier;\"><\/span><span style=\"font-family: courier new,courier;\">e.await_suspend<\/span>, and <span style=\"font-family: courier new,courier;\">e.await_resume<\/span>.<\/p>\n<p>The typical use case for <span style=\"font-family: courier new,courier;\">co_await<\/span> is a server that waits in a blocking fashion for events.<\/p>\n<div style=\"background: #ffffff none repeat scroll 0% 0%; overflow: auto; width: auto; border-width: 0.1em 0.1em 0.1em 0.8em;\">\n<table>\n<tbody>\n<tr>\n<td>\n<pre style=\"margin: 0px; line-height: 125%;\">1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7<\/pre>\n<\/td>\n<td>\n<pre style=\"margin: 0px; line-height: 125%;\">Acceptor acceptor{<span style=\"color: #0000dd; font-weight: bold;\">443<\/span>};\r\n<span style=\"color: #008800; font-weight: bold;\">while<\/span> (<span style=\"color: #007020;\">true<\/span>){\r\n  Socket socket<span style=\"color: #333333;\">=<\/span> acceptor.accept();              <span style=\"color: #888888;\">\/\/ blocking<\/span>\r\n  <span style=\"color: #008800; font-weight: bold;\">auto<\/span> request<span style=\"color: #333333;\">=<\/span> socket.read();                   <span style=\"color: #888888;\">\/\/ blocking<\/span>\r\n  <span style=\"color: #008800; font-weight: bold;\">auto<\/span> response<span style=\"color: #333333;\">=<\/span> handleRequest(request);     \r\n  socket.write(response);                        <span style=\"color: #888888;\">\/\/ blocking  <\/span>\r\n}\r\n<\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p>&nbsp;<\/p>\n<p>The server is quite simple because it sequentially answers each request in the same thread. The server is listening on port 443 (line 1), accepts its connections (line 3), reads the incoming data from the client (line 4), and write its answer to the client (line 6). The calls in line 3, 4, and 6 are blocking.<\/p>\n<p>Thanks to <span style=\"font-family: courier;\">co_await<\/span>, the blocking calls can now be suspended and resumed.<\/p>\n<div style=\"background: #ffffff none repeat scroll 0% 0%; overflow: auto; width: auto; border-width: 0.1em 0.1em 0.1em 0.8em;\">\n<table>\n<tbody>\n<tr>\n<td>\n<pre style=\"margin: 0px; line-height: 125%;\">1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7<\/pre>\n<\/td>\n<td>\n<pre style=\"margin: 0px; line-height: 125%;\">Acceptor acceptor{<span style=\"color: #0000dd; font-weight: bold;\">443<\/span>};\r\n<span style=\"color: #008800; font-weight: bold;\">while<\/span> (<span style=\"color: #007020;\">true<\/span>){\r\n  Socket socket<span style=\"color: #333333;\">=<\/span> co_await acceptor.accept();           \r\n  <span style=\"color: #008800; font-weight: bold;\">auto<\/span> request<span style=\"color: #333333;\">=<\/span> co_await socket.read();              \r\n  <span style=\"color: #008800; font-weight: bold;\">auto<\/span> response<span style=\"color: #333333;\">=<\/span> handleRequest(request);     \r\n  co_await socket.write(responste);                 \r\n}\r\n<\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<h2>What&#8217;s next?<\/h2>\n<p>The idea of transactional memory is based on transactions from the database theory. A transaction is an action that provides the properties <strong>A<\/strong>tomicity, <strong>C<\/strong>onsistency,<strong> I<\/strong>solation, and<strong> D<\/strong>urability (ACID). Transactional memory will be the topic of my <a href=\"https:\/\/www.modernescpp.com\/index.php\/transactional-memory\">next post.<\/a><\/p>\n<p>&nbsp;<\/p>\n<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Coroutines are functions that can suspend and resume their execution while keeping their state. The evolution in C++20 goes one step further.<\/p>\n","protected":false},"author":21,"featured_media":5201,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[367],"tags":[445],"class_list":["post-5202","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-multithreading-c-17-and-c-20","tag-coroutines"],"_links":{"self":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5202","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=5202"}],"version-history":[{"count":1,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5202\/revisions"}],"predecessor-version":[{"id":6882,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5202\/revisions\/6882"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media\/5201"}],"wp:attachment":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media?parent=5202"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=5202"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=5202"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}