{"id":6107,"date":"2021-03-06T21:16:19","date_gmt":"2021-03-06T21:16:19","guid":{"rendered":"https:\/\/www.modernescpp.com\/index.php\/an-infinite-data-stream-with-coroutines-in-c-20\/"},"modified":"2023-09-28T06:57:39","modified_gmt":"2023-09-28T06:57:39","slug":"an-infinite-data-stream-with-coroutines-in-c-20","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/an-infinite-data-stream-with-coroutines-in-c-20\/","title":{"rendered":"An Infinite Data Stream with Coroutines in C++20"},"content":{"rendered":"<p>In this post, I analyze the new keyword co_yield. Thanks to co_yield, you can create an infinite data stream in C++20.<\/p>\n<p><!--more--><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-8406 size-full\" style=\"display: block; margin-left: auto; margin-right: auto;\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/02\/TimelineCpp20Coroutines.png\" alt=\"\" width=\"1068\" height=\"383\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/02\/TimelineCpp20Coroutines.png 1068w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/02\/TimelineCpp20Coroutines-300x108.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/02\/TimelineCpp20Coroutines-1030x369.png 1030w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/02\/TimelineCpp20Coroutines-768x275.png 768w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/02\/TimelineCpp20Coroutines-705x253.png 705w\" sizes=\"auto, (max-width: 1068px) 100vw, 1068px\" \/><\/p>\n<p>This is what happened so far in my pragmatical journey through the new coroutine keywords <code>co_return,<\/code> <code>co_yield<\/code>, and <code>co_await.<\/code><\/p>\n<p><code>co_return<\/code>:<\/p>\n<ul>\n<li><a href=\"https:\/\/www.modernescpp.com\/index.php\/implementing-futures-with-coroutines\">Implementing Simple Futures With Coroutines<\/a><\/li>\n<li><a href=\"https:\/\/www.modernescpp.com\/index.php\/executing-a-future-in-a-separate-thread-with-coroutines\">Lazy Futures with Coroutines<\/a><\/li>\n<li><a href=\"https:\/\/www.modernescpp.com\/index.php\/executing-a-future-in-a-separate-thread-with-coroutines\">Executing a Future in a separate Thread with Coroutines<\/a><\/li>\n<\/ul>\n<h2>A Generator<\/h2>\n<p>As a starting point for further variations, I want to start with a generator which I only ask for three values. This simplification and visualization should help understand the generator&#8217;s control flow.<\/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: 0px; line-height: 125%;\"><span style=\"color: #0099ff; font-style: italic;\">\/\/ infiniteDataStreamComments.cpp<\/span>\n\n<span style=\"color: #009999;\">#include &lt;coroutine&gt;<\/span>\n<span style=\"color: #009999;\">#include &lt;memory&gt;<\/span>\n<span style=\"color: #009999;\">#include &lt;iostream&gt;<\/span>\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;\">struct<\/span> Generator {\n    \n    <span style=\"color: #006699; font-weight: bold;\">struct<\/span> promise_type;\n    <span style=\"color: #006699; font-weight: bold;\">using<\/span> handle_type <span style=\"color: #555555;\">=<\/span> std<span style=\"color: #555555;\">::<\/span>coroutine_handle<span style=\"color: #555555;\">&lt;<\/span>promise_type<span style=\"color: #555555;\">&gt;<\/span>;\n    \n    Generator(handle_type h)<span style=\"color: #555555;\">:<\/span> coro(h) {\n        std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"        Generator::Generator\"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\n    }                \n\n    handle_type coro;\n    \n    <span style=\"color: #555555;\">~<\/span>Generator() {\n        std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"        Generator::~Generator\"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\n        <span style=\"color: #006699; font-weight: bold;\">if<\/span> ( coro ) coro.destroy();\n    }\n    Generator(<span style=\"color: #006699; font-weight: bold;\">const<\/span> Generator<span style=\"color: #555555;\">&amp;<\/span>) <span style=\"color: #555555;\">=<\/span> <span style=\"color: #006699; font-weight: bold;\">delete<\/span>;\n    Generator<span style=\"color: #555555;\">&amp;<\/span> <span style=\"color: #006699; font-weight: bold;\">operator<\/span> <span style=\"color: #555555;\">=<\/span> (<span style=\"color: #006699; font-weight: bold;\">const<\/span> Generator<span style=\"color: #555555;\">&amp;<\/span>) <span style=\"color: #555555;\">=<\/span> <span style=\"color: #006699; font-weight: bold;\">delete<\/span>;\n    Generator(Generator<span style=\"color: #555555;\">&amp;&amp;<\/span> oth)<span style=\"color: #555555;\">:<\/span> coro(oth.coro) {\n        oth.coro <span style=\"color: #555555;\">=<\/span> nullptr;\n    }\n    Generator<span style=\"color: #555555;\">&amp;<\/span> <span style=\"color: #006699; font-weight: bold;\">operator<\/span> <span style=\"color: #555555;\">=<\/span> (Generator<span style=\"color: #555555;\">&amp;&amp;<\/span> oth) {\n        coro <span style=\"color: #555555;\">=<\/span> oth.coro;\n        oth.coro <span style=\"color: #555555;\">=<\/span> nullptr;\n        <span style=\"color: #006699; font-weight: bold;\">return<\/span> <span style=\"color: #555555;\">*<\/span><span style=\"color: #006699; font-weight: bold;\">this<\/span>;\n    }\n    T getNextValue() {\n        std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"        Generator::getNextValue\"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\n        coro.resume();                                                 <span style=\"color: #0099ff;\"> \/\/ (13)<\/span> \n        <span style=\"color: #006699; font-weight: bold;\">return<\/span> coro.promise().current_value;\n    }\n    <span style=\"color: #006699; font-weight: bold;\">struct<\/span> promise_type {\n        promise_type() {                                                <span style=\"color: #0099ff;\">\/\/ (2)<\/span>\n            std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"            promise_type::promise_type\"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\n        }                              \n          \n        <span style=\"color: #555555;\">~<\/span>promise_type() {\n            std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"            promise_type::~promise_type\"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\n        }\n        \n        std<span style=\"color: #555555;\">::<\/span>suspend_always initial_suspend() {                         <span style=\"color: #0099ff;\">\/\/ (5)<\/span>\n            std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"            promise_type::initial_suspend\"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;  \n            <span style=\"color: #006699; font-weight: bold;\">return<\/span> {};                                                 <span style=\"color: #0099ff;\"> \/\/ (6)<\/span>\n        }\n        std<span style=\"color: #555555;\">::<\/span>suspend_always final_suspend() noexcept {\n            std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"            promise_type::final_suspend\"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\n            <span style=\"color: #006699; font-weight: bold;\">return<\/span> {};\n        }\n        <span style=\"color: #006699; font-weight: bold;\">auto<\/span> get_return_object() {                                       <span style=\"color: #0099ff;\">\/\/ (3)<\/span>\n            std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"            promise_type::get_return_object\"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\n            <span style=\"color: #006699; font-weight: bold;\">return<\/span> Generator{handle_type<span style=\"color: #555555;\">::<\/span>from_promise(<span style=\"color: #555555;\">*<\/span><span style=\"color: #006699; font-weight: bold;\">this<\/span>)};          <span style=\"color: #0099ff;\">\/\/ (4)<\/span>\n        }\n      \n        std<span style=\"color: #555555;\">::<\/span>suspend_always yield_value(<span style=\"color: #007788; font-weight: bold;\">int<\/span> value) {                    <span style=\"color: #0099ff;\"> \/\/ (8)<\/span>\n            std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"            promise_type::yield_value\"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\n            current_value <span style=\"color: #555555;\">=<\/span> value;                                       <span style=\"color: #0099ff;\">\/\/ (9)<\/span>\n            <span style=\"color: #006699; font-weight: bold;\">return<\/span> {};                                                   <span style=\"color: #0099ff;\">\/\/ (10)<\/span>\n        }\n        <span style=\"color: #007788; font-weight: bold;\">void<\/span> return_void() {}\n        <span style=\"color: #007788; font-weight: bold;\">void<\/span> unhandled_exception() {\n            std<span style=\"color: #555555;\">::<\/span>exit(<span style=\"color: #ff6600;\">1<\/span>);\n        }\n\n        T current_value;\n    };\n\n};\n\nGenerator<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">int<\/span><span style=\"color: #555555;\">&gt;<\/span> getNext(<span style=\"color: #007788; font-weight: bold;\">int<\/span> start <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">10<\/span>, <span style=\"color: #007788; font-weight: bold;\">int<\/span> step <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">10<\/span>) {\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"    getNext: start\"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\n    <span style=\"color: #006699; font-weight: bold;\">auto<\/span> value <span style=\"color: #555555;\">=<\/span> start;\n    <span style=\"color: #006699; font-weight: bold;\">for<\/span> (<span style=\"color: #007788; font-weight: bold;\">true<\/span>) {                                             <span style=\"color: #0099ff;\">            \/\/ (11)<\/span>\n        std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"    getNext: before co_yield\"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\n        co_yield value;                                                <span style=\"color: #0099ff;\">  \/\/ (7)<\/span>\n        std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"    getNext: after co_yield\"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\n        value <span style=\"color: #555555;\">+=<\/span> step;\n    }\n}\n\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> main() {\n  \n    <span style=\"color: #006699; font-weight: bold;\">auto<\/span> gen <span style=\"color: #555555;\">=<\/span> getNext();                                                <span style=\"color: #0099ff;\">\/\/ (1)<\/span>\n    <span style=\"color: #006699; font-weight: bold;\">for<\/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> <span style=\"color: #ff6600;\">2<\/span>; <span style=\"color: #555555;\">++<\/span>i) {\n        <span style=\"color: #006699; font-weight: bold;\">auto<\/span> val <span style=\"color: #555555;\">=<\/span> gen.getNextValue();                                 <span style=\"color: #0099ff;\">  \/\/ (12)<\/span>\n        std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"main: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> val <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;                           <span style=\"color: #0099ff;\"> \/\/ (14)<\/span>\n    }\n    \n}\n<\/pre>\n<\/div>\n<div>\n<div>Executing\u00a0the\u00a0program\u00a0on\u00a0the\u00a0<a href=\"https:\/\/godbolt.org\/z\/cTW9Gq\">Compiler Explorer<\/a> makes\u00a0the\u00a0control\u00a0flow\u00a0transparent.<\/div>\n<div><\/div>\n<div><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-6103\" style=\"display: block; margin-left: auto; margin-right: auto;\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/03\/infiniteDataStreamComments.png\" alt=\"infiniteDataStreamComments\" width=\"450\" height=\"495\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/03\/infiniteDataStreamComments.png 550w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/03\/infiniteDataStreamComments-273x300.png 273w\" sizes=\"auto, (max-width: 450px) 100vw, 450px\" \/><\/div>\n<div>\n<p>Let&#8217;s analyze the control flow.<\/p>\n<p>The call<code> getNext()<\/code> (line 1) triggers the creation of the<code> Generator&lt;int&gt;<\/code>. First,\u00a0<code>promise_type<\/code> (line 2) is created, and the following <code>get_return_object<\/code> call (line 3) creates the generator (line 4) and stores it in a local variable. The result of this call is returned to the caller when the coroutine is suspended the first time. The initial suspension happens immediately (line 5). Because the member function call<code> initial_suspend<\/code> returns an Awaitable<code> std::suspend_always<\/code> (line 6), the control flow continues with the coroutine<code> getNext<\/code> until the instruction<code> co_yield value<\/code> (line 7). This call is mapped to the call<code> yield_value(int value)<\/code> (line 8), and the current value is prepared <code>current_value = value<\/code> (line 9). The member function <code>yield_value(int value)<\/code> returns the Awaitable <code>std::suspend_always<\/code> (line 10). Consequently, the execution of the coroutine pauses, the control flow goes back to the main function, and the for loop starts (line 11). The call<code> gen.getNextValue()<\/code> (line 12) starts the execution of the coroutine by resuming the coroutine using <code>coro.resume()<\/code> (line 13). Further, the function<code> getNextValue()<\/code> returns the current value prepared using the previously invoked member function <code>yield_value(int value)<\/code> (line 8). Finally, the generated number is displayed in line 14 and the for loop continues. In the end, the generator and the promise are destroyed.<\/p>\n<p>After this detailed analysis, I want first to modify the control flow.<\/p>\n<h3>Modifications<\/h3>\n<div>\n<div>My\u00a0code\u00a0snippets\u00a0and\u00a0line\u00a0numbers\u00a0are\u00a0all\u00a0based\u00a0on\u00a0the\u00a0previous\u00a0program<code> infiniteDataStreamComments.cpp<\/code>.\u00a0I\u00a0only\u00a0show\u00a0the\u00a0modifications.<\/div>\n<div><\/div>\n<h4>The Coroutine is Not Resumed<\/h4>\n<div>\n<div>\n<div>When\u00a0I\u00a0disable\u00a0the\u00a0resumption\u00a0of\u00a0the\u00a0coroutine\u00a0(<code>gen.getNextValue()<\/code> in\u00a0line 12)\u00a0and\u00a0the\u00a0display\u00a0of\u00a0its\u00a0value\u00a0(line 14),\u00a0the\u00a0coroutine\u00a0immediately\u00a0pauses.<\/div>\n<div><\/div>\n<\/div>\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: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">main<\/span>() {\n  \n    <span style=\"color: #006699; font-weight: bold;\">auto<\/span> gen <span style=\"color: #555555;\">=<\/span> getNext();\n    <span style=\"color: #006699; font-weight: bold;\">for<\/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> <span style=\"color: #ff6600;\">2<\/span>; <span style=\"color: #555555;\">++<\/span>i) {\n        <span style=\"color: #0099ff; font-style: italic;\">\/\/ auto val = gen.getNextValue();<\/span>\n        <span style=\"color: #0099ff; font-style: italic;\">\/\/ std::cout &lt;&lt; \"main: \" &lt;&lt; val &lt;&lt; '\\n';                   <\/span>\n    }\n    \n}\n<\/pre>\n<\/div>\n<\/div>\n<div><\/div>\n<div>\n<div>\n<div>The\u00a0coroutine\u00a0never\u00a0runs.\u00a0Consequently,\u00a0the\u00a0generator\u00a0and\u00a0its\u00a0promise\u00a0are\u00a0created\u00a0and\u00a0destroyed.<\/div>\n<div><\/div>\n<div><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-6104\" style=\"display: block; margin-left: auto; margin-right: auto;\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/03\/infiniteDataStreamCoroutineNeverRuns.png\" alt=\"infiniteDataStreamCoroutineNeverRuns\" width=\"350\" height=\"154\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/03\/infiniteDataStreamCoroutineNeverRuns.png 445w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/03\/infiniteDataStreamCoroutineNeverRuns-300x132.png 300w\" sizes=\"auto, (max-width: 350px) 100vw, 350px\" \/><\/div>\n<div><\/div>\n<h4><code>initial_suspend<\/code> Never Suspends<\/h4>\n<p>In the program, the member function<code> initial_suspend<\/code> returns the Awaitable <code>std::suspend_always<\/code> (line 5). As its name suggests, the Awaitable <code>std::suspends_always<\/code> causes the coroutine to pause immediately. Let me return <code>std::suspend_never<\/code> instead of <code>std::suspend_always<\/code>.<\/p>\n<\/div>\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%;\">std<span style=\"color: #555555;\">::<\/span>suspend_never initial_suspend() {  \n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"            promise_type::initial_suspend\"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\n    <span style=\"color: #006699; font-weight: bold;\">return<\/span> {};\n}\n<\/pre>\n<\/div>\n<\/div>\n<div>In this case, the coroutine runs immediately and pauses when the function<code> yield_value<\/code> (line 8) is invoked. A subsequent call <code>gen.getNextValue()<\/code> (line 12) resumes the coroutine and triggers the execution of the member function <code>yield_value<\/code> once more. The start value 10 is ignored, and the coroutine returns 20, 30, and 40.<\/div>\n<div><\/div>\n<div><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-6105\" style=\"display: block; margin-left: auto; margin-right: auto;\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/03\/infiniteDataStreamInitialSuspendSuspendsNever.png\" alt=\"infiniteDataStreamInitialSuspendSuspendsNever\" width=\"400\" height=\"499\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/03\/infiniteDataStreamInitialSuspendSuspendsNever.png 539w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/03\/infiniteDataStreamInitialSuspendSuspendsNever-240x300.png 240w\" sizes=\"auto, (max-width: 400px) 100vw, 400px\" \/><\/div>\n<div><\/div>\n<h4><code>yield_value<\/code> Never Suspends<\/h4>\n<div><\/div>\n<div>The call triggers the member function (line 8) <code>co_yield value<\/code> and prepares the current_value (line 9). The function returns the Awaitable <code>std::suspend_always<\/code> (line 10) and pauses the coroutine. Consequently, a subsequent call<code> gen.getNextValue<\/code> (line 12) has to resume the coroutine. When I change the return value of the member function <code>yield_value<\/code> to <code>std::suspend_never<\/code>, let me see what happens.<\/div>\n<div><\/div>\n<div><\/div>\n<\/div>\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%;\">std<span style=\"color: #555555;\">::<\/span>suspend_never yield_value(<span style=\"color: #007788; font-weight: bold;\">int<\/span> value) {    \n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"            promise_type::yield_value\"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\n    current_value <span style=\"color: #555555;\">=<\/span> value;\n    <span style=\"color: #006699; font-weight: bold;\">return<\/span> {};\n}\n<\/pre>\n<\/div>\n<\/div>\n<div><\/div>\n<div>\n<div>\n<div>As\u00a0you\u00a0may\u00a0guess,\u00a0the\u00a0while\u00a0loop\u00a0(line 1)\u00a0runs\u00a0forever,\u00a0and\u00a0the\u00a0coroutine returns nothing.<\/div>\n<div><\/div>\n<div><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-6106\" style=\"display: block; margin-left: auto; margin-right: auto;\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/03\/infiniteDataStreamCommentsYieldValueSuspendsNever.png\" alt=\"infiniteDataStreamCommentsYieldValueSuspendsNever\" width=\"400\" height=\"466\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/03\/infiniteDataStreamCommentsYieldValueSuspendsNever.png 509w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/03\/infiniteDataStreamCommentsYieldValueSuspendsNever-258x300.png 258w\" sizes=\"auto, (max-width: 400px) 100vw, 400px\" \/><\/div>\n<div><\/div>\n<div>@<a href=\"https:\/\/github.com\/mattgodbolt\">Matt Godbolt<\/a>: this was not a denial-of-service attack.<\/div>\n<h2>What&#8217;s next?<\/h2>\n<p>So far, I have never used the fact that the coroutine is a class template. In my <a href=\"https:\/\/www.modernescpp.com\/index.php\/a-generic-data-stream-with-coroutines-in-c-20\">next post,<\/a> I restructure the generator to produce a finite number of arbitrary values.<\/p>\n<div><\/div>\n<div><\/div>\n<div><\/div>\n<div><\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>In this post, I analyze the new keyword co_yield. Thanks to co_yield, you can create an infinite data stream in C++20.<\/p>\n","protected":false},"author":21,"featured_media":8406,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[375],"tags":[445],"class_list":["post-6107","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-c-20","tag-coroutines"],"_links":{"self":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/6107","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=6107"}],"version-history":[{"count":2,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/6107\/revisions"}],"predecessor-version":[{"id":8412,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/6107\/revisions\/8412"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media\/8406"}],"wp:attachment":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media?parent=6107"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=6107"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=6107"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}