{"id":6099,"date":"2021-03-04T11:54:31","date_gmt":"2021-03-04T11:54:31","guid":{"rendered":"https:\/\/www.modernescpp.com\/index.php\/lazy-futures-with-coroutines-in-c-20\/"},"modified":"2023-09-28T06:56:42","modified_gmt":"2023-09-28T06:56:42","slug":"lazy-futures-with-coroutines-in-c-20","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/lazy-futures-with-coroutines-in-c-20\/","title":{"rendered":"Lazy Futures with Coroutines"},"content":{"rendered":"<p>Based on the coroutines-based implementation of a simple future in my last post &#8220;<a href=\"https:\/\/www.modernescpp.com\/index.php\/implementing-futures-with-coroutines\">Implementing Simple Futures with Coroutines<\/a>&#8220;, I want to go today one giant step further. I analyze the workflow of the simple future and make it lazy.<\/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>Before I create future variations, you should understand its control flow. I assume you know my previous post: &#8220;<a href=\"https:\/\/www.modernescpp.com\/index.php\/implementing-futures-with-coroutines\">Implementing Simple Futures with Coroutines<\/a>. In this post, comments help me make the coroutine&#8217;s control flow transparent. Additionally, I added a link to an online compiler to each presented program so that you directly use and experiment with the programs.<\/p>\n<h2>The Transparent Control Flow<\/h2>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #0099ff; font-style: italic;\">\/\/ eagerFutureWithComments.cpp<\/span>\n\n<span style=\"color: #009999;\">#include &lt;coroutine&gt;<\/span>\n<span style=\"color: #009999;\">#include &lt;iostream&gt;<\/span>\n<span style=\"color: #009999;\">#include &lt;memory&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> MyFuture {\n    std<span style=\"color: #555555;\">::<\/span>shared_ptr<span style=\"color: #555555;\">&lt;<\/span>T<span style=\"color: #555555;\">&gt;<\/span> value\n    MyFuture(std<span style=\"color: #555555;\">::<\/span>shared_ptr<span style=\"color: #555555;\">&lt;<\/span>T<span style=\"color: #555555;\">&gt;<\/span> p)<span style=\"color: #555555;\">:<\/span> value(p) {                         <span style=\"color: #0099ff; font-style: italic;\">\/\/ (3)<\/span>\n        std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"    MyFuture::MyFuture\"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\n    }\n    <span style=\"color: #555555;\">~<\/span>MyFuture() { \n        std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"    MyFuture::~MyFuture\"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\n    }\n    T get() {\n        std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"    MyFuture::get\"<\/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: #555555;\">*<\/span>value;\n    }\n\n    <span style=\"color: #006699; font-weight: bold;\">struct<\/span> promise_type {                                              <span style=\"color: #0099ff; font-style: italic;\">\/\/ (4)<\/span>\n        std<span style=\"color: #555555;\">::<\/span>shared_ptr<span style=\"color: #555555;\">&lt;<\/span>T<span style=\"color: #555555;\">&gt;<\/span> ptr <span style=\"color: #555555;\">=<\/span> std<span style=\"color: #555555;\">::<\/span>make_shared<span style=\"color: #555555;\">&lt;<\/span>T<span style=\"color: #555555;\">&gt;<\/span>();                <span style=\"color: #0099ff; font-style: italic;\">\/\/ (11)<\/span>\n        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        <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        MyFuture<span style=\"color: #555555;\">&lt;<\/span>T<span style=\"color: #555555;\">&gt;<\/span> get_return_object() {\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> ptr;\n        }\n        <span style=\"color: #007788; font-weight: bold;\">void<\/span> return_value(T v) {\n            std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"        promise_type::return_value\"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\n            <span style=\"color: #555555;\">*<\/span>ptr <span style=\"color: #555555;\">=<\/span> v;\n        }\n        std<span style=\"color: #555555;\">::<\/span>suspend_never initial_suspend() {                         <span style=\"color: #0099ff; font-style: italic;\">\/\/ (6)<\/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> {};\n        }\n        std<span style=\"color: #555555;\">::<\/span>suspend_never final_suspend() noexcept {                 <span style=\"color: #0099ff; font-style: italic;\">\/\/ (7)<\/span>\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: #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    };                                                                 <span style=\"color: #0099ff; font-style: italic;\">\/\/ (5)<\/span>\n};\n\nMyFuture<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">int<\/span><span style=\"color: #555555;\">&gt;<\/span> createFuture() {                                         <span style=\"color: #0099ff; font-style: italic;\">\/\/ (2)<\/span>\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"createFuture\"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\n    co_return <span style=\"color: #ff6600;\">2021<\/span>;\n}\n\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> main() {\n\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\n\n    <span style=\"color: #006699; font-weight: bold;\">auto<\/span> fut <span style=\"color: #555555;\">=<\/span> createFuture();                                         <span style=\"color: #0099ff; font-style: italic;\">\/\/ (1)<\/span>\n    <span style=\"color: #006699; font-weight: bold;\">auto<\/span> res <span style=\"color: #555555;\">=<\/span> fut.get();                                              <span style=\"color: #0099ff; font-style: italic;\">\/\/ (8)<\/span>\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"res: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> res <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\n\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\n\n}                                                                     <span style=\"color: #0099ff; font-style: italic;\">\/\/ (12)<\/span>\n<\/pre>\n<\/div>\n<p>The call <code>createFuture<\/code> (line 1) causes the creation of the instance of<code> MyFuture<\/code> (line 2). Before <code>MyFuture<\/code> &#8216;s constructor call (line 3) is completed, the promise <code>promise_type<\/code> is created, executed, and destroyed (lines 4 &#8211; 5). The promise uses the awaitable (lines 6 and 7) in each step of its control flow and, hence, never suspends. It has to be allocated to save the result of the promise for the later call (line 8). Furthermore, the used <code>std::shared_ptr'<\/code>s ensure (lines 3 and 10) that the program does not cause a memory leak. As a local, <code>fut <\/code>goes out of scope in line 12, and the C++ run time calls its destructor.<\/p>\n<p>You can try out the program on <a href=\"https:\/\/godbolt.org\/z\/Y9naEx\">Compiler Explorer<\/a>.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-6096\" style=\"display: block; margin-left: auto; margin-right: auto;\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/03\/eagerFutureWithComments.png\" alt=\"eagerFutureWithComments\" width=\"400\" height=\"305\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/03\/eagerFutureWithComments.png 488w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/03\/eagerFutureWithComments-300x229.png 300w\" sizes=\"auto, (max-width: 400px) 100vw, 400px\" \/><\/p>\n<p>The presented coroutine runs immediately and is, therefore, eager. Furthermore, the coroutine runs in the thread of the caller.<\/p>\n<p>Let&#8217;s make the future lazy.<\/p>\n<h2>A Lazy Future<\/h2>\n<p>A lazy future is a future that runs only if asked for the value. Let&#8217;s see what I must change in the previous coroutine to make the future lazy.<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #0099ff; font-style: italic;\">\/\/ lazyFuture.cpp<\/span>\n\n<span style=\"color: #009999;\">#include &lt;coroutine&gt;<\/span>\n<span style=\"color: #009999;\">#include &lt;iostream&gt;<\/span>\n<span style=\"color: #009999;\">#include &lt;memory&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> MyFuture {\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    handle_type coro;                                               <span style=\"color: #0099ff; font-style: italic;\">\/\/ (5)<\/span>\n\n    MyFuture(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;\">\"    MyFuture::MyFuture\"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\n    }\n    <span style=\"color: #555555;\">~<\/span>MyFuture() { \n        std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"    MyFuture::~MyFuture\"<\/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();                                 <span style=\"color: #0099ff; font-style: italic;\">\/\/ (8)<\/span>\n    }\n\n    T get() {\n        std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"    MyFuture::get\"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\n        coro.resume();                                              <span style=\"color: #0099ff; font-style: italic;\">\/\/ (6)<\/span>\n        <span style=\"color: #006699; font-weight: bold;\">return<\/span> coro.promise().result;\n    }\n\n    <span style=\"color: #006699; font-weight: bold;\">struct<\/span> promise_type {\n\t\tT result;\n        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        <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        <span style=\"color: #006699; font-weight: bold;\">auto<\/span> get_return_object() {                                  <span style=\"color: #0099ff; font-style: italic;\">\/\/ (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> MyFuture{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        <span style=\"color: #007788; font-weight: bold;\">void<\/span> return_value(T v) {\n            std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"        promise_type::return_value\"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\n            result <span style=\"color: #555555;\">=<\/span> v;\n        }\n        std<span style=\"color: #555555;\">::<\/span>suspend_always initial_suspend() {                    <span style=\"color: #0099ff; font-style: italic;\">\/\/ (1)<\/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> {};\n        }\n        std<span style=\"color: #555555;\">::<\/span>suspend_always final_suspend() noexcept {            <span style=\"color: #0099ff; font-style: italic;\">\/\/ (2)<\/span>\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: #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};\n\nMyFuture<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">int<\/span><span style=\"color: #555555;\">&gt;<\/span> createFuture() {\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"createFuture\"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\n    co_return <span style=\"color: #ff6600;\">2021<\/span>;\n}\n\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> main() {\n\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\n\n    <span style=\"color: #006699; font-weight: bold;\">auto<\/span> fut <span style=\"color: #555555;\">=<\/span> createFuture();                                        <span style=\"color: #0099ff; font-style: italic;\">\/\/ (4)<\/span>\n    <span style=\"color: #006699; font-weight: bold;\">auto<\/span> res <span style=\"color: #555555;\">=<\/span> fut.get();                                             <span style=\"color: #0099ff; font-style: italic;\">\/\/ (7)<\/span>\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"res: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> res <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\n\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\n\n}\n<\/pre>\n<\/div>\n<p>Let&#8217;s first study the promise. The promise always suspends at the beginning (line 1) and the end (line 2). Furthermore, the member function <code>get_return_object<\/code> (line 3) creates the return object that is returned to the caller of the coroutine c<code>reateFuture<\/code> (line 4). The future <code>MyFuture<\/code> is more interesting. It has a handle <code>coro<\/code> (line 5) to the promise. <code>MyFuture<\/code> uses the handle to manage its promise. It resumes the promise (line 6), asks for the promise for the result (line 7), and finally destroys it (line 8). The resumption of the coroutine is necessary because it never runs automatically (line 1). When the client invokes<code> fut.get()<\/code> (line 7) to ask for the result of the future, it implicitly resumes the promise (line 6).<\/p>\n<p>You can try out the program on <a href=\"https:\/\/godbolt.org\/z\/EejWcj\">Compiler Explorer<\/a>.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-6097\" style=\"display: block; margin-left: auto; margin-right: auto;\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/03\/lazyFuture.png\" alt=\"lazyFuture\" width=\"400\" height=\"322\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/03\/lazyFuture.png 479w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/03\/lazyFuture-300x242.png 300w\" sizes=\"auto, (max-width: 400px) 100vw, 400px\" \/><\/p>\n<p>What happens if the client is not interested in the result of the future and, hence, does not resume the coroutine? Let&#8217;s try it out.<\/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;\">'\\n'<\/span>;\n\n    <span style=\"color: #006699; font-weight: bold;\">auto<\/span> fut <span style=\"color: #555555;\">=<\/span> createFuture();\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ auto res = fut.get();<\/span>\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ std::cout &lt;&lt; \"res: \" &lt;&lt; res &lt;&lt; '\\n';<\/span>\n\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\n\n}\n<\/pre>\n<\/div>\n<p>As you may guess, the promise never runs, and the member functions <code>return_value<\/code> and<code> final_suspend<\/code> are not executed.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-6098\" style=\"display: block; margin-left: auto; margin-right: auto;\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/03\/lazyFutureWithoutGet.png\" alt=\"lazyFutureWithoutGet\" width=\"400\" height=\"202\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/03\/lazyFutureWithoutGet.png 445w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/03\/lazyFutureWithoutGet-300x152.png 300w\" sizes=\"auto, (max-width: 400px) 100vw, 400px\" \/><\/p>\n<p>Before I end this post, I want to write about the lifetime challenges of coroutines.<\/p>\n<h2>Lifetime Challenges of Coroutines<\/h2>\n<p>One of the challenges of dealing with coroutines is handling the lifetime of the coroutine.<\/p>\n<p>In the first program <code>eagerFutureWithComments.cpp<\/code>, I stored the coroutine result in a <code>std::shared_ptr<\/code>. This is critical because the coroutine is eagerly executed.<\/p>\n<p>In the program<code> lazyFuture.cpp<\/code>, the call <code>final_suspend<\/code> always suspends (line 2): <code>std::suspend_always final_suspend()<\/code>. Consequently, the promise outlives the client, and a <code>std::shared_ptr<\/code> is not necessary anymore. Returning <code>std::suspend_never<\/code> from the function<code> final_suspend<\/code> would cause, in this case, undefined behavior because the client would outlive the promise. Hence, the lifetime of the <code>result<\/code> ends before the client asks for it.<\/p>\n<h2>What&#8217;s next?<\/h2>\n<p>My final step in the variation of the future is still missing. In the <a href=\"https:\/\/www.modernescpp.com\/index.php\/executing-a-future-in-a-separate-thread-with-coroutines\">next post, <\/a>I will resume the coroutine on a separate thread.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Based on the coroutines-based implementation of a simple future in my last post &#8220;Implementing Simple Futures with Coroutines&#8220;, I want to go today one giant step further. I analyze the workflow of the simple future and make it lazy.<\/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,446],"class_list":["post-6099","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-c-20","tag-coroutines","tag-tasks"],"_links":{"self":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/6099","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=6099"}],"version-history":[{"count":2,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/6099\/revisions"}],"predecessor-version":[{"id":8409,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/6099\/revisions\/8409"}],"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=6099"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=6099"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=6099"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}