{"id":6095,"date":"2021-02-22T20:33:51","date_gmt":"2021-02-22T20:33:51","guid":{"rendered":"https:\/\/www.modernescpp.com\/index.php\/implementing-futures-with-coroutines\/"},"modified":"2023-09-28T06:56:01","modified_gmt":"2023-09-28T06:56:01","slug":"implementing-futures-with-coroutines","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/implementing-futures-with-coroutines\/","title":{"rendered":"Implementing Simple Futures with Coroutines"},"content":{"rendered":"<p>Instead of <code>return<\/code>, a coroutine uses<code> co_return<\/code> returning its result. In this post, I want to implement a simple coroutine using co_return.<\/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>You may wonder: Although I have presented the theory behind <a href=\"https:\/\/www.modernescpp.com\/index.php\/tag\/coroutines\">coroutines<\/a>, I want to write once more about coroutines. My answer is straightforward and based on my experience. C++20 does not provide concrete coroutines. Instead, C++20 provides a framework for implementing coroutines. This framework consists of more than 20 functions, some of which you must implement and others can override. Based on these functions, the compiler generates two workflows, which define the behavior of the coroutine. To make it short. Coroutines in C++20 are double-edged swords. On one side, they give you enormous power; on the other side, they are pretty challenging to understand. I dedicated over 80 pages to coroutines in my book &#8220;<a href=\"https:\/\/leanpub.com\/c20\">C++20: Get the Details<\/a>&#8220;, which has not yet explained everything.<\/p>\n<p>From my experience, using simple coroutines and modifying them is the easiest &#8211; maybe only &#8211; way to understand them. And this is precisely the approach I&#8217;m pursuing in the following posts. I present simple coroutines and modify them. To make the workflow obvious, I put many comments inside and added only so much theory necessary to understand the internals of coroutines. My explanations are not complete and should only serve as a starting point to deepen your knowledge about coroutines.<\/p>\n<h2>A Short Reminder<\/h2>\n<p>While you can only call a <strong>function<\/strong> and return from it, you can call a <strong>coroutine<\/strong>, suspend and resume it, and destroy a suspended coroutine.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-6093\" style=\"display: block; margin-left: auto; margin-right: auto;\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/02\/FunctionsVersusCoroutines.png\" alt=\"FunctionsVersusCoroutines\" width=\"500\" height=\"268\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/02\/FunctionsVersusCoroutines.png 1238w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/02\/FunctionsVersusCoroutines-300x161.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/02\/FunctionsVersusCoroutines-1024x549.png 1024w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/02\/FunctionsVersusCoroutines-768x412.png 768w\" sizes=\"auto, (max-width: 500px) 100vw, 500px\" \/><\/p>\n<p>With the new keywords <code>co_await<\/code> and <code>co_yield<\/code>, C++20 extends the execution of C++ functions with two new concepts.<\/p>\n<p>Thanks to <code>co_await expression<\/code> it is possible to suspend and resume the execution of the expression. If you use <code>co_await expression<\/code> in a function <code>func<\/code>, the call <code>auto getResult = func()<\/code> does not block if the function call&#8217;s result is unavailable. Instead of resource-consuming blocking, you have resource-friendly waiting.<br \/>\n<code><\/code><\/p>\n<p><code>co_yield<\/code> expression supports generator functions. The generator function returns a new value each time you call it. A generator function is a data stream from which you can pick values. The data stream can be infinite. Therefore, we are at the center of lazy evaluation with C++.<\/p>\n<p>Additionally, a coroutine does not <code>return<\/code> its result, a coroutine does<code> co_return<\/code>\u00a0 its result.<\/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%;\">\/\/ ...\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    co_return <span style=\"color: #ff6600;\">2021<\/span>;\n}\n\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> main() {\n\n    <span style=\"color: #006699; font-weight: bold;\">auto<\/span> fut <span style=\"color: #555555;\">=<\/span> createFuture();\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"fut.get(): \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> fut.get() <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\n\n}   \n<\/pre>\n<\/div>\n<p>In this straightforward example <code>createFuture<\/code> is the coroutine because it uses one of the three new keywords <code>co_return, co_yield,<\/code> or <code>co_await<\/code> and it returns a coroutine<code> MyFuture&lt;int&gt;<\/code>. What? This is what often puzzled me. The name coroutine is used for two entities. Let me introduce two new terms. <code>createFuture<\/code> is a <strong>coroutine factory <\/strong>that returns a <strong>coroutine object<\/strong> <code>fut, <\/code>that can be used to ask for the result: <code>fut.get()<\/code>.<\/p>\n<p>This theory should be enough. Let&#8217;s talk about <code>co_return<\/code>.<\/p>\n<h2>co_return<\/h2>\n<p>Admittedly, the coroutine in the following program<code> eagerFuture.cpp<\/code> is the simplest coroutine, I can imagine that still does something meaningful: it automatically stores the result of its invocation.<\/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;\">\/\/ eagerFuture.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;                           <span style=\"color: #0099ff; font-style: italic;\">\/\/ (3)<\/span>\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) {}\n    <span style=\"color: #555555;\">~<\/span>MyFuture() { }\n    T get() {                                          <span style=\"color: #0099ff; font-style: italic;\">\/\/ (10)<\/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 {\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;\">\/\/ (4)<\/span>\n        <span style=\"color: #555555;\">~<\/span>promise_type() { }\n        <span style=\"color: #006699; font-weight: bold;\">MyFuture&lt;T&gt;<\/span> get_return_object() {              <span style=\"color: #0099ff; font-style: italic;\">\/\/ (7)<\/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            <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;\">\/\/ (5)<\/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;\">\/\/ (6)<\/span>\n            <span style=\"color: #006699; font-weight: bold;\">return<\/span> {};\n        }\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() {                         <span style=\"color: #0099ff; font-style: italic;\">\/\/ (1)<\/span>\n    co_return <span style=\"color: #ff6600;\">2021<\/span>;                                    <span style=\"color: #0099ff; font-style: italic;\">\/\/ (9)<\/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();\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"fut.get(): \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> fut.get() <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;   <span style=\"color: #0099ff; font-style: italic;\">\/\/ (2)<\/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><code>MyFuture<\/code> behaves as a future, which runs immediately (see &#8220;<a href=\"https:\/\/www.modernescpp.com\/index.php\/asynchronous-function-calls\">Asynchronous Function Calls<\/a>&#8220;). The call of the coroutine <code>createFuture<\/code> (line 1) returns the future, and the call<code> fut.get<\/code> (line 2) picks up the result of the associated promise.<\/p>\n<p>There is one subtle difference to a future: the return value of the coroutine <code>createFuture<\/code> is available after its invocation. Due to the lifetime issues of the coroutine, the coroutine is managed by a <code>std::shared_ptr<\/code> (lines 3 and 4). The coroutine always uses <code>std::suspend_never<\/code> (lines 5 and 6) and, therefore, neither does suspend before it runs nor after. This means the coroutine is immediately executed when the function <code>createFuture<\/code> is invoked. The member function <code>get_return_object<\/code> (line 7) returns the handle to the coroutine and stores it in a local variable. <code>return_value<\/code> (lines 8) stores the result of the coroutine, which was provided by <code>co_return 2021<\/code> (line 9). The client invokes <code>fut.get<\/code> (line 2) and uses the future as a handle to the promise. The member function<code> get<\/code> finally returns the result to the client (line 10).<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-6094\" style=\"display: block; margin-left: auto; margin-right: auto;\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/02\/eagerFuture.png\" alt=\"eagerFuture\" width=\"150\" height=\"43\" \/><\/p>\n<p>You may think it is not worth implementing a coroutine that behaves just like a function. You are right! However, this simple coroutine is an ideal starting point for writing various implementations of futures.<\/p>\n<p>At this point, I should add a bit of theory.<\/p>\n<h2>The Promise Workflow<\/h2>\n<p>When you use<code> co_yield<\/code>, <code>co_await<\/code>, or <code>co_return<\/code> in a function, the function becomes a coroutine, and the compiler transforms its function body into something equivalent to the following lines.<\/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%;\">{\n  Promise prom;                      <span style=\"color: #0099ff; font-style: italic;\">\/\/ (1)<\/span>\n  co_await prom.initial_suspend();   <span style=\"color: #0099ff; font-style: italic;\">\/\/ (2)<\/span>\n  try {                                         \n    <span style=\"color: #555555;\">&lt;<\/span>function body<span style=\"color: #555555;\">&gt;                  <span style=\"color: #0099ff; font-style: italic;\">\/\/ (3)<\/span><\/span>\n  }\n  <span style=\"color: #006699; font-weight: bold;\">catch<\/span> (...) {\n    prom.unhandled_exception();\n  }\n<span style=\"color: #9999ff;\">FinalSuspend:<\/span>\n  co_await prom.final_suspend();     <span style=\"color: #0099ff; font-style: italic;\">\/\/ (4)<\/span>\n}\n<\/pre>\n<\/div>\n<p>Do these function names sound familiar to you? Right! These are the member functions of the inner class<code> promise_type<\/code>. Here are the steps the compiler performs when it creates the coroutine object as the return value of the coroutine factory <code>createFuture<\/code>. It first creates the promise object (line 1), invokes its <code>initial_suspend<\/code> member function (line 2), executes the body of the coroutine factory (line 3), and finally, calls the member function<code> final_suspend<\/code> (line 4). Both member functions <code>initial_suspend<\/code> and <code>final_suspend<\/code> in the program <code>eagerFuture.cpp<\/code> return the predefined awaitables<code> std::suspend_never<\/code>.\u00a0 As its name suggests, this awaitable suspends never; hence, the coroutine object suspends never and behaves such as a usual function. An awaitable is something you can await on. The operator co_await needs an awaitable. I will write a post about the awaitable and the second awaiter workflow.<\/p>\n<p>From this simplified promise workflow, you can deduce which member functions the promise (<code>promise_type<\/code>) at least needs:<\/p>\n<ul>\n<li>A default constructor<\/li>\n<li><code>initial_suspend<\/code><\/li>\n<li><code>final_suspend<\/code><\/li>\n<li><code>unhandled_exception<\/code><\/li>\n<\/ul>\n<p>Admittedly, this was not the full explanation but at least enough to get the first intuition about the workflow of coroutines.<\/p>\n<h2>What&#8217;s next?<\/h2>\n<p>You may already guess it. In my <a href=\"https:\/\/www.modernescpp.com\/index.php\/lazy-futures-with-coroutines-in-c-20\">next post,<\/a> I will use this simple coroutine as a starting point for further experiments. First, I add comments to the program to make its workflow explicit, second, I make the coroutine lazy and resume it on another thread.<\/p>\n<div id=\"simple-translate\"><\/div>\n","protected":false},"excerpt":{"rendered":"<p>Instead of return, a coroutine uses co_return returning its result. In this post, I want to implement a simple coroutine using co_return.<\/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-6095","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\/6095","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=6095"}],"version-history":[{"count":2,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/6095\/revisions"}],"predecessor-version":[{"id":8407,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/6095\/revisions\/8407"}],"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=6095"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=6095"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=6095"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}