{"id":6113,"date":"2021-03-07T21:04:04","date_gmt":"2021-03-07T21:04:04","guid":{"rendered":"https:\/\/www.modernescpp.com\/index.php\/starting-jobs-with-coroutines\/"},"modified":"2023-09-28T07:41:02","modified_gmt":"2023-09-28T07:41:02","slug":"starting-jobs-with-coroutines","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/starting-jobs-with-coroutines\/","title":{"rendered":"Starting Jobs with Coroutines"},"content":{"rendered":"<p>C++20 has three new keywords to make a coroutine out of a function: <code>co_return<\/code>, <code>co_yield<\/code>, and <code>co_await<\/code>. <code>co_await<\/code> requires an Awaitable as arguments and starts the Awaiter workflow. Let me show in this post what that means.<\/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>To understand this post, you should have a basic understanding of coroutines. Here are my previous posts to coroutines, presenting coroutines from the practical perspective.<\/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\/lazy-futures-with-coroutines-in-c-20\">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<p><code>co_yield:<\/code><\/p>\n<ul>\n<li><a href=\"https:\/\/www.modernescpp.com\/index.php\/an-infinite-data-stream-with-coroutines-in-c-20\">An Infinite Data Stream with Coroutines<\/a><\/li>\n<li><a href=\"https:\/\/www.modernescpp.com\/index.php\/a-generic-data-stream-with-coroutines-in-c-20\">A Generic Data Stream with Coroutines<\/a><\/li>\n<\/ul>\n<p>Before implementing Awaitables and showing their applications, I should write about the awaiter workflow.<\/p>\n<h2>The Awaiter Workflow<\/h2>\n<p>First, I have a short reminder. The awaiter workflow is based on the member functions of the Awaitable:<code> await_ready()<\/code>,<code> await_suspend()<\/code>, and <code>await_resume().<\/code> C++20 has the two predefined Awaitables <code>std::suspend_always<\/code> and <code>std::suspend_never<\/code>, which I heavily used in this mini-series to coroutines.<\/p>\n<ul>\n<li><code>std::suspend_always<\/code><\/li>\n<\/ul>\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: #006699; font-weight: bold;\">struct<\/span> suspend_always {\n    constexpr <span style=\"color: #007788; font-weight: bold;\">bool<\/span> await_ready() <span style=\"color: #006699; font-weight: bold;\">const<\/span> noexcept { <span style=\"color: #006699; font-weight: bold;\">return<\/span> <span style=\"color: #336666;\">false<\/span>; }\n    constexpr <span style=\"color: #007788; font-weight: bold;\">void<\/span> await_suspend(std<span style=\"color: #555555;\">::<\/span>coroutine_handle<span style=\"color: #555555;\">&lt;&gt;<\/span>) <span style=\"color: #006699; font-weight: bold;\">const<\/span> noexcept {}\n    constexpr <span style=\"color: #007788; font-weight: bold;\">void<\/span> await_resume() <span style=\"color: #006699; font-weight: bold;\">const<\/span> noexcept {}\n};\n<\/pre>\n<\/div>\n<ul>\n<li><code>std::suspend_never<\/code><\/li>\n<\/ul>\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: #006699; font-weight: bold;\">struct<\/span> suspend_never {\n    constexpr <span style=\"color: #007788; font-weight: bold;\">bool<\/span> await_ready() <span style=\"color: #006699; font-weight: bold;\">const<\/span> noexcept { <span style=\"color: #006699; font-weight: bold;\">return<\/span> <span style=\"color: #336666;\">true<\/span>; }\n    constexpr <span style=\"color: #007788; font-weight: bold;\">void<\/span> await_suspend(std<span style=\"color: #555555;\">::<\/span>coroutine_handle<span style=\"color: #555555;\">&lt;&gt;<\/span>) <span style=\"color: #006699; font-weight: bold;\">const<\/span> noexcept {}\n    constexpr <span style=\"color: #007788; font-weight: bold;\">void<\/span> await_resume() <span style=\"color: #006699; font-weight: bold;\">const<\/span> noexcept {}\n};\n<\/pre>\n<\/div>\n<p>Here is the awaiter workflow in prose.<\/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%;\">awaitable.await_ready() returns <span style=\"color: #336666;\">false<\/span><span style=\"color: #555555;\">:              <span style=\"color: #3366ff;\">     \/\/ (1)<\/span><\/span>\n    \n    suspend coroutine\n\t\n    awaitable.await_suspend(coroutineHandle) returns<span style=\"color: #555555;\">:<\/span>   <span style=\"color: #3366ff;\"> \/\/ (3)<\/span>\n\t\n        <span style=\"color: #007788; font-weight: bold;\">void<\/span><span style=\"color: #555555;\">:                                            <span style=\"color: #3366ff;\">\/\/ (4)<\/span><\/span>\n            awaitable.await_suspend(coroutineHandle);\n            coroutine keeps suspended\n            <span style=\"color: #006699; font-weight: bold;\">return<\/span> to caller\n\n        <span style=\"color: #9999ff;\">bool:                                            <span style=\"color: #3366ff;\">\/\/ (5)<\/span><\/span>\n            <span style=\"color: #007788; font-weight: bold;\">bool<\/span> result <span style=\"color: #555555;\">=<\/span> awaitable.await_suspend(coroutineHandle);\n            <span style=\"color: #006699; font-weight: bold;\">if<\/span> result<span style=\"color: #555555;\">:<\/span> \n                coroutine keep suspended\n                <span style=\"color: #006699; font-weight: bold;\">return<\/span> to caller\n            <span style=\"color: #9999ff;\">else:<\/span> \n                go to resumptionPoint\n\n        another coroutine handle<span style=\"color: #555555;\">:<\/span>\t                <span style=\"color: #3366ff;\"> \/\/ (6)<\/span>\n            <span style=\"color: #006699; font-weight: bold;\">auto<\/span> anotherCoroutineHandle <span style=\"color: #555555;\">=<\/span> awaitable.await_suspend(coroutineHandle);\n            anotherCoroutineHandle.resume();\n            <span style=\"color: #006699; font-weight: bold;\">return<\/span> to caller\n\t\n<span style=\"color: #9999ff;\">resumptionPoint:<\/span>\n\n<span style=\"color: #006699; font-weight: bold;\">return<\/span> awaitable.await_resume();                    <span style=\"color: #3366ff;\">     \/\/ (2)\n<\/span><\/pre>\n<\/div>\n<p>The workflow is only executed if<code> awaitable.await_ready()<\/code> returns <code>false<\/code> (line 1). In case it returns <code>true<\/code>, the coroutine is ready and returns with the result of the call <code>awaitable.await_resume()<\/code> (line 2).<\/p>\n<p>Let me assume that <code>awaitable.await_ready()<\/code> returns <code>false<\/code>. First, the coroutine is suspended (line 3), and the return value is immediately evaluated. The return type can be <code>void<\/code> (line 4), a boolean (line 5), or another coroutine handle (line 6), such as <code>anotherCoroutineHandle.<\/code> Depending on the return type, the program flow returns, or another coroutine is executed.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-6110\" style=\"display: block; margin-left: auto; margin-right: auto;\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/03\/awaiterWorkflow.png\" alt=\"awaiterWorkflow\" width=\"700\" height=\"173\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/03\/awaiterWorkflow.png 986w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/03\/awaiterWorkflow-300x74.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/03\/awaiterWorkflow-768x190.png 768w\" sizes=\"auto, (max-width: 700px) 100vw, 700px\" \/><\/p>\n<p>Let me apply the theory and start a job on request.<\/p>\n<h2>Starting a Job on Request<\/h2>\n<p>The coroutine in the following example is as simple as it can be. It awaits on the predefined Awaitable <code>std::suspend_never()<\/code>.<\/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;\">\/\/ startJob.cpp<\/span>\n\n<span style=\"color: #009999;\">#include &lt;coroutine&gt;<\/span>\n<span style=\"color: #009999;\">#include &lt;iostream&gt;<\/span>\n \n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> Job { \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    handle_type coro;\n    Job(handle_type h)<span style=\"color: #555555;\">:<\/span> coro(h){}\n    <span style=\"color: #555555;\">~<\/span>Job() {\n        <span style=\"color: #006699; font-weight: bold;\">if<\/span> ( coro ) coro.destroy();\n    }\n    <span style=\"color: #007788; font-weight: bold;\">void<\/span> start() {\n        coro.resume();                                    <span style=\"color: #0099ff;\">\/\/ (6)<\/span> \n    }\n\n\n    <span style=\"color: #006699; font-weight: bold;\">struct<\/span> promise_type {\n        <span style=\"color: #006699; font-weight: bold;\">auto<\/span> get_return_object() { \n            <span style=\"color: #006699; font-weight: bold;\">return<\/span> Job{handle_type<span style=\"color: #555555;\">::<\/span>from_promise(<span style=\"color: #555555;\">*<\/span><span style=\"color: #006699; font-weight: bold;\">this<\/span>)};\n        }\n        std<span style=\"color: #555555;\">::<\/span>suspend_always initial_suspend() {          <span style=\"color: #0099ff;\"> \/\/ (4)<\/span>\n            std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"    Preparing job\"<\/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        std<span style=\"color: #555555;\">::<\/span>suspend_always final_suspend() noexcept {    <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;\">\"    Performing job\"<\/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: #007788; font-weight: bold;\">void<\/span> return_void() {}\n        <span style=\"color: #007788; font-weight: bold;\">void<\/span> unhandled_exception() {}\n    \n    };\n};\n \nJob <span style=\"color: #cc00ff;\">prepareJob<\/span>() {                                        <span style=\"color: #0099ff;\">\/\/ (1)<\/span>\n    co_await std<span style=\"color: #555555;\">::<\/span>suspend_never();                       <span style=\"color: #0099ff;\"> \/\/ (2)<\/span>\n}\n \n<span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">main<\/span>() {\n\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span>  <span style=\"color: #cc3300;\">\"Before job\"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\n\n    <span style=\"color: #006699; font-weight: bold;\">auto<\/span> job <span style=\"color: #555555;\">=<\/span> prepareJob();                             <span style=\"color: #0099ff;\"> \/\/ (3)<\/span>                       \n    job.start();                                        <span style=\"color: #0099ff;\">  \/\/ (5)<\/span>  \n\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span>  <span style=\"color: #cc3300;\">\"After job\"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span>  <span style=\"color: #cc3300;\">'\\n'<\/span>;\n\n}\n<\/pre>\n<\/div>\n<p>You may think that the coroutine <code>prepareJob<\/code> (line 1) is meaningless because the Awaitable always suspends. No! The function <code>prepareJob<\/code> is at least a coroutine factory using <code>co_await<\/code> (line 2) and returning a coroutine object. The function call <code>prepareJob()<\/code> in line 3 creates the coroutine object of type <code>Job<\/code>. When you study the data type Job, you recognize that the coroutine object is immediately suspended because the member function of the promise returns the Awaitable <code>std::suspend_always<\/code> (line 5). This is precisely why the function call <code>job.start<\/code> (line 5) is necessary to resume the coroutine (line 6). The member function <code>final_suspend<\/code>() also returns <code>std::suspend_always<\/code> (line 27).<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-6111\" style=\"display: block; margin-left: auto; margin-right: auto;\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/03\/startJob.png\" alt=\"startJob\" width=\"200\" height=\"101\" \/><\/p>\n<p>The program <code>startJob.cpp<\/code> is an ideal starting point for further experiments. First, making the workflow transparent eases its understanding.<\/p>\n<h2>The Transparent Awaiter Workflow<\/h2>\n<p>I added a few comments to the previous program.<\/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;\">\/\/ startJobWithComments.cpp<\/span>\n\n<span style=\"color: #009999;\">#include &lt;coroutine&gt;<\/span>\n<span style=\"color: #009999;\">#include &lt;iostream&gt;<\/span>\n\n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> MySuspendAlways {                                 <span style=\"color: #0099ff;\"> \/\/ (1)<\/span>\n    <span style=\"color: #007788; font-weight: bold;\">bool<\/span> await_ready() <span style=\"color: #006699; font-weight: bold;\">const<\/span> noexcept { \n        std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"        MySuspendAlways::await_ready\"<\/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: #336666;\">false<\/span>; \n    }\n    <span style=\"color: #007788; font-weight: bold;\">void<\/span> await_suspend(std<span style=\"color: #555555;\">::<\/span>coroutine_handle<span style=\"color: #555555;\">&lt;&gt;<\/span>) <span style=\"color: #006699; font-weight: bold;\">const<\/span> noexcept {\n        std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"        MySuspendAlways::await_suspend\"<\/span>  <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\n\n    }\n    <span style=\"color: #007788; font-weight: bold;\">void<\/span> await_resume() <span style=\"color: #006699; font-weight: bold;\">const<\/span> noexcept {\n        std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"        MySuspendAlways::await_resume\"<\/span>  <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\n    }\n};\n\n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> MySuspendNever {                                <span style=\"color: #0099ff;\">  \/\/ (2)<\/span>\n    <span style=\"color: #007788; font-weight: bold;\">bool<\/span> await_ready() <span style=\"color: #006699; font-weight: bold;\">const<\/span> noexcept { \n        std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"        MySuspendNever::await_ready\"<\/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: #336666;\">true<\/span>; \n    }\n    <span style=\"color: #007788; font-weight: bold;\">void<\/span> await_suspend(std<span style=\"color: #555555;\">::<\/span>coroutine_handle<span style=\"color: #555555;\">&lt;&gt;<\/span>) <span style=\"color: #006699; font-weight: bold;\">const<\/span> noexcept {\n        std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"        MySuspendNever::await_suspend\"<\/span>  <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\n\n    }\n    <span style=\"color: #007788; font-weight: bold;\">void<\/span> await_resume() <span style=\"color: #006699; font-weight: bold;\">const<\/span> noexcept {\n        std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"        MySuspendNever::await_resume\"<\/span>  <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\n    }\n};\n \n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> Job { \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    handle_type coro;\n    Job(handle_type h)<span style=\"color: #555555;\">:<\/span> coro(h){}\n    <span style=\"color: #555555;\">~<\/span>Job() {\n        <span style=\"color: #006699; font-weight: bold;\">if<\/span> ( coro ) coro.destroy();\n    }\n    <span style=\"color: #007788; font-weight: bold;\">void<\/span> start() {\n        coro.resume();\n    }\n\n\n    <span style=\"color: #006699; font-weight: bold;\">struct<\/span> promise_type {\n        <span style=\"color: #006699; font-weight: bold;\">auto<\/span> get_return_object() { \n            <span style=\"color: #006699; font-weight: bold;\">return<\/span> Job{handle_type<span style=\"color: #555555;\">::<\/span>from_promise(<span style=\"color: #555555;\">*<\/span><span style=\"color: #006699; font-weight: bold;\">this<\/span>)};\n        }\n        MySuspendAlways initial_suspend() {        <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;\">\"    Job prepared\"<\/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        MySuspendAlways final_suspend() noexcept { <span style=\"color: #0099ff;\"> \/\/ (4)<\/span>\n            std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"    Job finished\"<\/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: #007788; font-weight: bold;\">void<\/span> return_void() {}\n        <span style=\"color: #007788; font-weight: bold;\">void<\/span> unhandled_exception() {}\n    \n    };\n};\n \nJob <span style=\"color: #cc00ff;\">prepareJob<\/span>() {\n    co_await MySuspendNever();                     <span style=\"color: #0099ff;\">\/\/ (5)<\/span>\n}\n \n<span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">main<\/span>() {\n\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span>  <span style=\"color: #cc3300;\">\"Before job\"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\n\n    <span style=\"color: #006699; font-weight: bold;\">auto<\/span> job <span style=\"color: #555555;\">=<\/span> prepareJob();                      <span style=\"color: #0099ff;\">\/\/ (6)<\/span>\n    job.start();                                <span style=\"color: #0099ff;\">  \/\/ (7)\n<\/span>\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span>  <span style=\"color: #cc3300;\">\"After job\"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span>  <span style=\"color: #cc3300;\">'\\n'<\/span>;\n\n}\n<\/pre>\n<\/div>\n<p>First, I replaced the predefined Awaitables<code> std::suspend_always<\/code> and<code> std::suspend_never<\/code> with Awaitables <code>MySuspendAlways<\/code> (line 1) and <code>MySuspendNever<\/code> (line 2). I use them in lines 3, 4, and 5. The Awaitables mimic the behavior of the predefined Awaitables but additionally write a comment. Due to the use of <code>std::cout<\/code>, the member functions <code>await_ready<\/code>, <code>await_suspend<\/code>, and <code>await_resume<\/code> cannot be declared as <code>constexpr<\/code>.<\/p>\n<p>The screenshot of the program execution shows the control flow nicely, which you can observe on the <a href=\"https:\/\/godbolt.org\/z\/T5rcE4\">Compiler Explorer<\/a>.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-6112\" style=\"display: block; margin-left: auto; margin-right: auto;\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/03\/startJobWithComments.png\" alt=\"startJobWithComments\" width=\"400\" height=\"254\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/03\/startJobWithComments.png 492w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/03\/startJobWithComments-300x190.png 300w\" sizes=\"auto, (max-width: 400px) 100vw, 400px\" \/><\/p>\n<p>The function <code>initial_suspend<\/code> (line 3) is executed at the beginning of the coroutine and the function<code> final_suspend<\/code> at its end (line 4). The call <code>prepareJob()<\/code> (line 6) triggers the creation of the coroutine object, and the function call<code> job.start()<\/code> its resumption and, hence, completion (line 7). Consequently, the members<code> await_ready<\/code>, <code>await_suspend<\/code>, and <code>await_resume<\/code> of <code>MySuspendAlways<\/code> are executed. When you don&#8217;t resume the Awaitable, such as the coroutine object returned by the member function<code> final_suspend<\/code>, the function<code> await_resume<\/code> is not processed. In contrast, the Awaitable&#8217;s <code>MySuspendNever<\/code>\u00a0the function is immediately ready because <code>await_ready<\/code> returns <code>true<\/code> and, hence, does not suspend.<\/p>\n<div>\n<div>Thanks\u00a0to\u00a0the\u00a0comments,\u00a0you\u00a0should\u00a0have\u00a0an\u00a0elementary\u00a0understanding\u00a0of\u00a0the awaiter\u00a0workflow. Now,\u00a0it&#8217;s\u00a0time\u00a0to\u00a0vary\u00a0it.<\/div>\n<h2>What&#8217;s next?<\/h2>\n<div><\/div>\n<\/div>\n<p>In my <a href=\"https:\/\/www.modernescpp.com\/index.php\/automatically-resuming-a-job-with-coroutines\">next posts<\/a>,\u00a0 I automatically resume the Awaiter on the same and, finally, on a separate thread.<\/p>\n<hr \/>\n","protected":false},"excerpt":{"rendered":"<p>C++20 has three new keywords to make a coroutine out of a function: co_return, co_yield, and co_await. co_await requires an Awaitable as arguments and starts the Awaiter workflow. Let me show in this post what that means.<\/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-6113","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\/6113","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=6113"}],"version-history":[{"count":2,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/6113\/revisions"}],"predecessor-version":[{"id":8415,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/6113\/revisions\/8415"}],"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=6113"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=6113"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=6113"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}