{"id":6116,"date":"2021-03-09T06:31:18","date_gmt":"2021-03-09T06:31:18","guid":{"rendered":"https:\/\/www.modernescpp.com\/index.php\/automatically-resuming-a-job-with-coroutines\/"},"modified":"2023-09-28T07:41:30","modified_gmt":"2023-09-28T07:41:30","slug":"automatically-resuming-a-job-with-coroutines","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/automatically-resuming-a-job-with-coroutines\/","title":{"rendered":"Automatically Resuming a Job with Coroutines on a Separate Thread"},"content":{"rendered":"<p>In my last post &#8220;<a href=\"https:\/\/www.modernescpp.com\/index.php\/starting-jobs-with-coroutines\">Starting Jobs with Coroutines<\/a>&#8220;, I applied <code>co_await<\/code> to start a job. In this post, I improve the workflow and automatically resume a job if necessary. In my final step, I resume the job on a separate thread.<\/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 my 7th post in my mini-series about the new keywords co_return, co_yield, and co_await. To understand this practical introduction to coroutines, you should know all the previous posts:<\/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><code>co_await:<\/code><\/p>\n<ul>\n<li><a href=\"https:\/\/www.modernescpp.com\/index.php\/starting-jobs-with-coroutines\">Starting Jobs with Coroutines<\/a><\/li>\n<\/ul>\n<h2>Automatically Resuming the Awaiter<\/h2>\n<p>In the previous workflow (see <a href=\"https:\/\/www.modernescpp.com\/index.php\/starting-jobs-with-coroutines\">Starting Jobs with Coroutines<\/a>), I presented the awaiter workflow in detail, and I explicitly started the job.<\/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: #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();\n    job.start();\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>This explicit invoking of<code> job.start()<\/code> was necessary because <code>await_ready<\/code> in the Awaitable <code>MySuspendAlways<\/code> always returned <code>false<\/code>. Now let&#8217;s assume that await_ready can return <code>true<\/code> or <code>false<\/code> and the job is not explicitly started. A short reminder: When <code>await_ready<\/code> returns <code>true<\/code>, the function <code>await_resume<\/code> is directly invoked but not <code>await_suspend<\/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;\">\/\/ startJobWithAutomaticResumption.cpp<\/span>\n\n<span style=\"color: #009999;\">#include &lt;coroutine&gt;<\/span>\n<span style=\"color: #009999;\">#include &lt;functional&gt;<\/span>\n<span style=\"color: #009999;\">#include &lt;iostream&gt;<\/span>\n<span style=\"color: #009999;\">#include &lt;random&gt;<\/span>\n\nstd<span style=\"color: #555555;\">::<\/span>random_device seed;\n<span style=\"color: #006699; font-weight: bold;\">auto<\/span> gen <span style=\"color: #555555;\">=<\/span> std<span style=\"color: #555555;\">::<\/span>bind_front(std<span style=\"color: #555555;\">::<\/span>uniform_int_distribution<span style=\"color: #555555;\">&lt;&gt;<\/span>(<span style=\"color: #ff6600;\">0<\/span>,<span style=\"color: #ff6600;\">1<\/span>),         <span style=\"color: #0099ff;\">\/\/ (1)<\/span>\n                           std<span style=\"color: #555555;\">::<\/span>default_random_engine(seed()));\n\n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> MySuspendAlways {                                                 <span style=\"color: #0099ff;\">\/\/ (3)<\/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: #cc00ff;\">gen<\/span>();\n    }\n    <span style=\"color: #007788; font-weight: bold;\">bool<\/span> await_suspend(std<span style=\"color: #555555;\">::<\/span>coroutine_handle<span style=\"color: #555555;\">&lt;&gt;<\/span> handle) <span style=\"color: #006699; font-weight: bold;\">const<\/span> noexcept {  <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;\">\"        MySuspendAlways::await_suspend\"<\/span>  <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\n        handle.resume();                                                <span style=\"color: #0099ff;\"> \/\/ (6)<\/span>\n        <span style=\"color: #006699; font-weight: bold;\">return<\/span> <span style=\"color: #336666;\">true<\/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 {                                 <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;\">\"        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> 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\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;\"> \/\/ (2)<\/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        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;\">\"    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;\">performJob<\/span>() {\n    co_await std<span style=\"color: #555555;\">::<\/span>suspend_never();\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 jobs\"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\n\n    performJob();\n    performJob();\n    performJob();\n    performJob();\n\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span>  <span style=\"color: #cc3300;\">\"After jobs\"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span>  <span style=\"color: #cc3300;\">'\\n'<\/span>;\n\n}\n<\/pre>\n<\/div>\n<p>First, the coroutine is now called <code>performJob<\/code> and runs automatically. <code>gen<\/code> (line 1) is a random number generator for the numbers 0 or 1. It uses the default random engine for its job, initialized with the seed. Thanks to<code> std::bind_front<\/code>, I can bind it together with the <code>std::uniform_int_distribution<\/code> to get a callable which, when used, gives me a random number 0 or 1.<\/p>\n<p>A callable is something that behaves like a function. Not only are these named functions but also function objects or lambda expressions. Read more about the new function<code> std::bind_front<\/code> in the post &#8220;<a href=\"https:\/\/www.modernescpp.com\/index.php\/more-and-more-utilities-in-c-20\">More and More Utilities in C++20<\/a>&#8220;.<\/p>\n<p>I removed in this example the awaitables with predefined Awaitables from the C++ standard, except the awaitable <code>MySuspendAlways<\/code> as the return type of the member function <code>initial_suspend<\/code> (line 2). <code>await_ready<\/code> (line 3) returns a boolean. When the boolean is <code>true<\/code>, the control flow jumps directly to the member function <code>await_resume<\/code> (line 4), when <code>false<\/code>, the coroutine is immediately suspended and, therefore, the function <code>await_suspend<\/code> runs (line 5). The function <code>await_suspend<\/code> gets the handle to the coroutine and uses it to resume the coroutine (line 6). Instead of returning the value <code>true<\/code>, await_suspend can also return <code>void<\/code>.<\/p>\n<p>The following screenshot shows: When <code>await_ready<\/code> returns <code>true<\/code>, the function <code>await_resume<\/code> is called, when <code>await_ready<\/code> returns <code>false<\/code>, the function <code>await_suspend<\/code> is also called.<\/p>\n<div>\n<div>You\u00a0can\u00a0try\u00a0out\u00a0the\u00a0program\u00a0on <a href=\"https:\/\/godbolt.org\/z\/8b1Y14\">Compiler Explorer<\/a>.<\/div>\n<div><\/div>\n<div><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-6114\" style=\"display: block; margin-left: auto; margin-right: auto;\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/03\/startJobWithAutomaticResumption.png\" alt=\"startJobWithAutomaticResumption\" width=\"463\" height=\"536\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/03\/startJobWithAutomaticResumption.png 463w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/03\/startJobWithAutomaticResumption-259x300.png 259w\" sizes=\"auto, (max-width: 463px) 100vw, 463px\" \/><\/div>\n<div><\/div>\n<div>Let me make the final step and automatically resume the awaiter on a separate thread.<\/div>\n<div><\/div>\n<h2>Automatically Resuming the Awaiter on a Separate Thread<\/h2>\n<p>The following program is based on the previous program.<\/p>\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: 0px; line-height: 125%;\"><span style=\"color: #0099ff; font-style: italic;\">\/\/ startJobWithAutomaticResumptionOnThread.cpp<\/span>\n\n<span style=\"color: #009999;\">#include &lt;coroutine&gt;<\/span>\n<span style=\"color: #009999;\">#include &lt;functional&gt;<\/span>\n<span style=\"color: #009999;\">#include &lt;iostream&gt;<\/span>\n<span style=\"color: #009999;\">#include &lt;random&gt;<\/span>\n<span style=\"color: #009999;\">#include &lt;thread&gt;<\/span>\n<span style=\"color: #009999;\">#include &lt;vector&gt;<\/span>\n\nstd<span style=\"color: #555555;\">::<\/span>random_device seed;\n<span style=\"color: #006699; font-weight: bold;\">auto<\/span> gen <span style=\"color: #555555;\">=<\/span> std<span style=\"color: #555555;\">::<\/span>bind_front(std<span style=\"color: #555555;\">::<\/span>uniform_int_distribution<span style=\"color: #555555;\">&lt;&gt;<\/span>(<span style=\"color: #ff6600;\">0<\/span>,<span style=\"color: #ff6600;\">1<\/span>), \n                           std<span style=\"color: #555555;\">::<\/span>default_random_engine(seed()));\n \n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> MyAwaitable {\n    std<span style=\"color: #555555;\">::<\/span>jthread<span style=\"color: #555555;\">&amp;<\/span> outerThread;\n    <span style=\"color: #007788; font-weight: bold;\">bool<\/span> <span style=\"color: #cc00ff;\">await_ready<\/span>() <span style=\"color: #006699; font-weight: bold;\">const<\/span> noexcept {                    \n        <span style=\"color: #006699; font-weight: bold;\">auto<\/span> res <span style=\"color: #555555;\">=<\/span> gen();\n        <span style=\"color: #006699; font-weight: bold;\">if<\/span> (res) std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\" (executed)\"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\n        <span style=\"color: #006699; font-weight: bold;\">else<\/span> std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\" (suspended)\"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\n        <span style=\"color: #006699; font-weight: bold;\">return<\/span> res;                                        <span style=\"color: #0099ff;\">\/\/ (6)<\/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> h) {        <span style=\"color: #0099ff;\">\/\/ (7)<\/span>\n        outerThread <span style=\"color: #555555;\">=<\/span> std<span style=\"color: #555555;\">::<\/span>jthread([h] { h.resume(); });  <span style=\"color: #0099ff;\"> \/\/ (8)<\/span>\n    }\n    <span style=\"color: #007788; font-weight: bold;\">void<\/span> await_resume() {}\n};\n\n \n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> Job{\n    <span style=\"color: #006699; font-weight: bold;\">static<\/span> <span style=\"color: #006699; font-weight: bold;\">inline<\/span> <span style=\"color: #007788; font-weight: bold;\">int<\/span> JobCounter{<span style=\"color: #ff6600;\">1<\/span>};\n    Job() {\n        <span style=\"color: #555555;\">++<\/span>JobCounter;\n    }\n    \n    <span style=\"color: #006699; font-weight: bold;\">struct<\/span> promise_type {\n        <span style=\"color: #007788; font-weight: bold;\">int<\/span> JobNumber{JobCounter};\n        Job <span style=\"color: #cc00ff;\">get_return_object<\/span>() { <span style=\"color: #006699; font-weight: bold;\">return<\/span> {}; }\n        std<span style=\"color: #555555;\">::<\/span>suspend_never initial_suspend() {        <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;\">\"    Job \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> JobNumber <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\" prepared on thread \"<\/span> \n                      <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>this_thread<span style=\"color: #555555;\">::<\/span>get_id();\n            <span style=\"color: #006699; font-weight: bold;\">return<\/span> {}; \n        }\n        std<span style=\"color: #555555;\">::<\/span>suspend_never final_suspend() noexcept {  <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 \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> JobNumber <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\" finished on thread \"<\/span> \n                      <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>this_thread<span style=\"color: #555555;\">::<\/span>get_id() <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 \nJob <span style=\"color: #cc00ff;\">performJob<\/span>(std<span style=\"color: #555555;\">::<\/span>jthread<span style=\"color: #555555;\">&amp;<\/span> out) {\n    co_await MyAwaitable{out};                     <span style=\"color: #0099ff;\">   \/\/ (1)<\/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>vector<span style=\"color: #555555;\">&lt;<\/span>std<span style=\"color: #555555;\">::<\/span>jthread<span style=\"color: #555555;\">&gt;<\/span> threads(<span style=\"color: #ff6600;\">8<\/span>);             <span style=\"color: #0099ff;\">\/\/ (4)<\/span>\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> threads) performJob(thr);        <span style=\"color: #0099ff;\"> \/\/ (5)<\/span>\n\n}\n<\/pre>\n<\/div>\n<p>The main difference with the previous program is the new awaitable <code>MyAwaitable<\/code>, used in the coroutine <code>performJob<\/code> (line 1). On the contrary, the coroutine object returned from the coroutine <code>performJob<\/code> is straightforward. Essentially, its member functions <code>initial_suspend<\/code> (line 2) and <code>final_suspend<\/code> (line 3) return the predefined awaitable <code>std::suspend_never.<\/code> Additionally, both functions show the <code>JobNumber<\/code> of the executed job and the thread ID on which it runs. The screenshot shows which coroutine runs immediately and which one is suspended. Thanks to the thread id, you can observe that suspended coroutines are resumed on a different thread.<\/p>\n<div>\n<div>You\u00a0can\u00a0try\u00a0out\u00a0the\u00a0program\u00a0on\u00a0the <a href=\"https:\/\/wandbox.org\/permlink\/skHgWKF0SYAwp8Dm\">Wandbox<\/a>.<\/div>\n<div><\/div>\n<div><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-6115\" style=\"display: block; margin-left: auto; margin-right: auto;\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/03\/startJobWithAutomaticResumptionOnThread.png\" alt=\"startJobWithAutomaticResumptionOnThread\" width=\"450\" height=\"315\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/03\/startJobWithAutomaticResumptionOnThread.png 593w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/03\/startJobWithAutomaticResumptionOnThread-300x210.png 300w\" sizes=\"auto, (max-width: 450px) 100vw, 450px\" \/><\/div>\n<div><\/div>\n<div>Let me discuss the interesting control flow of the program. Line 4 creates eight default-constructed threads, which the coroutine <code>performJob<\/code> (line 5) takes by reference. Further, the reference becomes the argument for creating <code>MyAwaitable{out}<\/code> (line 1). Depending on the value of <code>res<\/code> (line 6), and, therefore, the return value of the function <code>await_read<\/code>y, the Awaitable continues (<code>res<\/code> is <code>true<\/code>) to run or is suspended (<code>res<\/code> is <code>false<\/code>). In case <code>MyAwaitable<\/code> is suspended, the function <code>await_suspend<\/code> (line 7) is executed. Thanks to the assignment of <code>outerThread<\/code> (line 8), it becomes a running thread. The running threads must outlive the lifetime of the coroutine. For this reason, the threads have the scope of the <code>main<\/code> function.<\/div>\n<div><\/div>\n<h2>What&#8217;s next?<\/h2>\n<p>DONE: I have written almost 100 posts about C++20. In my <a href=\"https:\/\/www.modernescpp.com\/index.php\/quo-vadids-modernes-c\">next post, <\/a>I want to say a few concluding words about C++20 and answer the question &#8220;What&#8217;s next&#8221; regarding C++.<\/p>\n<div><\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>In my last post &#8220;Starting Jobs with Coroutines&#8220;, I applied co_await to start a job. In this post, I improve the workflow and automatically resume a job if necessary. In my final step, I resume the job on a separate thread.<\/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-6116","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\/6116","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=6116"}],"version-history":[{"count":2,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/6116\/revisions"}],"predecessor-version":[{"id":8416,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/6116\/revisions\/8416"}],"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=6116"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=6116"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=6116"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}