{"id":3922,"date":"2020-06-22T11:30:48","date_gmt":"2020-06-22T09:30:48","guid":{"rendered":"https:\/\/mariusbancila.ro\/blog\/?p=3922"},"modified":"2020-06-24T09:56:10","modified_gmt":"2020-06-24T07:56:10","slug":"a-cpp20-coroutine-example","status":"publish","type":"post","link":"https:\/\/mariusbancila.ro\/blog\/2020\/06\/22\/a-cpp20-coroutine-example\/","title":{"rendered":"A C++20 coroutine example"},"content":{"rendered":"<p>One of the most important new features in the C++20 is coroutines. A coroutine is a function that has the ability to be suspended and resumed. A function becomes a coroutine if it uses any of the following:<\/p>\n<ul>\n<li>the <tt>co_await<\/tt> operator to suspend execution until resumed<\/li>\n<li>the <tt>co_return<\/tt> keyword to complete execution and optionally return a value<\/li>\n<li>the <tt>co_yield<\/tt> keyword to suspend execution and return a value<\/li>\n<\/ul>\n<p>A coroutine must also have a return type that satisfies some requirements. However, the C++20 standard, only defines a framework for the execution of coroutines, but does not define any coroutine types satisfying such requirements. That means, we need to either write our own or rely on 3rd party libraries for this. In this post, I&#8217;ll show how to write some simple examples using the <a href=\"https:\/\/github.com\/lewissbaker\/cppcoro\/\" rel=\"noopener noreferrer\" target=\"_blank\">cppcoro<\/a> library.<br \/>\n<!-- more --><\/p>\n<p>The cppcoro library contains abstractions for the C++20 coroutines, including task<T>, generator<T>, and async_generator<T>. A task represents an asynchronous computation that is executed lazily (that means only when the coroutine is awaited) and a generator is a sequence of values of some <tt>T<\/tt> type, that are produced lazily (that is, when the <tt>begin()<\/tt> function is called to retrieve an iterator or the <tt>++<\/tt> operator is called on the iterator).<\/p>\n<p>Let us look at an example. The function <tt>produce_items()<\/tt> below is a coroutine, because it uses the <tt>co_yield<\/tt> keyword to return a value and has the return type <tt>cppcoro::generator&lt;std::string&gt;<\/tt> that satisfies the requirements of a generator coroutine. <\/p>\n<pre class=\"lang:c++ decode:true \" >#include &lt;cppcoro\/generator.hpp&gt;\r\n\r\ncppcoro::generator&lt;std::string&gt; produce_items()\r\n{\r\n  while (true)\r\n  {\r\n     auto v = rand();\r\n     using namespace std::string_literals;\r\n     auto i = \"item \"s + std::to_string(v);\r\n     print_time();\r\n     std::cout &lt;&lt; \"produced \" &lt;&lt; i &lt;&lt; '\\n';\r\n     co_yield i;\r\n  }\r\n}\r\n<\/pre>\n<p><strong>NOTE<\/strong>: the use of the <tt>rand()<\/tt> function is for simplicity only. Do not use this obsolete function for production code.<\/p>\n<p>This function has an infinite loop, but the execution is suspended when the <tt>co_yield<\/tt> statement executes. This function produces a random number each time it is resumed. This happens when the generator is being iterated. And example is shown below:<\/p>\n<pre class=\"lang:c++ decode:true \" >#include &lt;cppcoro\/task.hpp&gt;\r\n\r\ncppcoro::task&lt;&gt; consume_items(int const n)\r\n{\r\n  int i = 1;\r\n  for(auto const&amp; s : produce_items())\r\n  {\r\n     print_time();\r\n     std::cout &lt;&lt; \"consumed \" &lt;&lt; s &lt;&lt; '\\n';\r\n     if (++i &gt; n) break;\r\n  }\r\n\r\n  co_return;\r\n}<\/pre>\n<p>The <tt>consume_items<\/tt> function is also a coroutine. It uses the <tt>co_return<\/tt> keyword to complete execution and its return type is <tt>cppcodo::task&lt;&gt;<\/tt>, which also satisfies the requirements for a coroutine type. This function runs a loop <tt>n<\/tt> times using a range-based for loop. This loop calls the begin() function of the <tt>cppcoro::generator&lt;std::string&gt;<\/tt> class and retrieves an iterator that is later incremented with <tt>operator++<\/tt>. The <tt>produce_items()<\/tt> is resumed upon each of these calls and returns a new (random) value. If an exception occurs, it is re-throwned to the caller from the invocation of <tt>begin()<\/tt> or <tt>operator++<\/tt>. The <tt>produce_items()<\/tt> function could be resumed indefinitely, although the consuming code only does so for a finite number of times.<\/p>\n<p>The <tt>consume_items()<\/tt> can be invoked from the <tt>main()<\/tt> function. However, because <tt>main()<\/tt> cannot be a coroutine, it cannot use the <tt>co_await<\/tt> operator to await for the completion of its execution. To help with that, the cppcoro library provides a function called <tt>sync_wait()<\/tt> that synchronously waits until the specified awaitable completes (which is awaited on the current thread inside a newly created coroutine). This function blocks the current thread until the operation completes and returns the result of the <tt>co_await<\/tt> expression. In an exception occurs, it is rethrown to the caller.<\/p>\n<p>The following snipper shows how we can invoke and wait for <tt>consume_items()<\/tt> from <tt>main()<\/tt>:<\/p>\n<pre class=\"lang:c++ decode:true \" >#include &lt;cppcoro\/sync_wait.hpp&gt;\r\n\r\nint main()\r\n{\r\n   cppcoro::sync_wait(consume_items(5));\r\n}<\/pre>\n<p>The output from running this program is as follows:<br \/>\n<img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/mariusbancila.ro\/blog\/wp-content\/uploads\/2020\/06\/time1.png\" alt=\"\" width=\"411\" height=\"313\" class=\"alignnone size-full wp-image-3924\" srcset=\"https:\/\/mariusbancila.ro\/blog\/wp-content\/uploads\/2020\/06\/time1.png 411w, https:\/\/mariusbancila.ro\/blog\/wp-content\/uploads\/2020\/06\/time1-300x228.png 300w\" sizes=\"auto, (max-width: 411px) 100vw, 411px\" \/><\/p>\n<p>The <tt>cppcoro::generator&lt;T&gt;<\/tt> produces values in a lazy but synchronously way. That means, using the <tt>co_await<\/tt> operator from a coroutine returning this type is not possible. However, the cppcoro library features an asynchronous generator, called <tt>cppcoro::async_generator&lt;T&gt;<\/tt>, that makes this possible. <\/p>\n<p>We can change the preceding example as follows: a new coroutine, <tt>next_value()<\/tt> returns a value that takes some time to be computed. We simulate that by awaiting for a random number of seconds. The <tt>produce_items()<\/tt> coroutine waits for a new value in each loop and then returns a new item from that value. The return type, this time, is <tt>cppcoro::async_generator&lt;T&gt;<\/tt>.<\/p>\n<pre class=\"lang:c++ decode:true \" >#include &lt;cppcoro\/async_generator.hpp&gt;\r\n\r\ncppcoro::task&lt;int&gt; next_value()\r\n{\r\n  using namespace std::chrono_literals;\r\n  co_await std::chrono::seconds(1 + rand() % 5);\r\n  co_return rand();\r\n}\r\n\r\ncppcoro::async_generator&lt;std::string&gt; produce_items()\r\n{\r\n  while (true)\r\n  {\r\n     auto v = co_await next_value();\r\n     using namespace std::string_literals;\r\n     auto i = \"item \"s + std::to_string(v);\r\n     print_time();\r\n     std::cout &lt;&lt; \"produced \" &lt;&lt; i &lt;&lt; '\\n';\r\n     co_yield i;\r\n  }\r\n}<\/pre>\n<p>The consumer requires a slight change, because it has to await for each new value. This is done with the use of the <tt>co_await<\/tt> operator in the for loop as follows:<\/p>\n<pre class=\"lang:c++ decode:true \" >cppcoro::task&lt;&gt; consume_items(int const n)\r\n{\r\n  int i = 1;\r\n  for co_await(auto const&amp; s : produce_items())\r\n  {\r\n     print_time();\r\n     std::cout &lt;&lt; \"consumed \" &lt;&lt; s &lt;&lt; '\\n';\r\n     if (++i &gt; n) break;\r\n  }\r\n}<\/pre>\n<p>The <tt>co_return<\/tt> statement is no longer present in this implementation, although it could be added. Because the <tt>co_await<\/tt> is used in the for loop, the function is coroutine. You do not need to add empty <tt>co_return<\/tt> statements at the end of a coroutine returning <tt>cppcoro::task&lt;&gt;<\/tt>, just like you don&#8217;t need empty <tt>return<\/tt> statements at the end of a regular function returning <tt>void<\/tt>. The previous implementation required this statement because there was no call to <tt>co_await<\/tt>, therefore, the <tt>co_return<\/tt> was necessary to make the function a coroutine.<\/p>\n<p>There are no changes required to the <tt>main()<\/tt> function. However, when we execute the code this time, each value is produced after some random time interval, as the following image shows:<br \/>\n<img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/mariusbancila.ro\/blog\/wp-content\/uploads\/2020\/06\/time2.png\" alt=\"\" width=\"411\" height=\"317\" class=\"alignnone size-full wp-image-3925\" srcset=\"https:\/\/mariusbancila.ro\/blog\/wp-content\/uploads\/2020\/06\/time2.png 411w, https:\/\/mariusbancila.ro\/blog\/wp-content\/uploads\/2020\/06\/time2-300x231.png 300w\" sizes=\"auto, (max-width: 411px) 100vw, 411px\" \/><\/p>\n<p>For the sake of completeness, the <tt>print_time()<\/tt> function referred in these snippets is as follows:<\/p>\n<pre class=\"lang:c++ decode:true \" >void print_time()\r\n{\r\n   auto now = std::chrono::system_clock::now();\r\n   std::time_t time = std::chrono::system_clock::to_time_t(now);   \r\n\r\n   char mbstr[100];\r\n   if (std::strftime(mbstr, sizeof(mbstr), \"[%H:%M:%S] \", std::localtime(&amp;time))) \r\n   {\r\n      std::cout &lt;&lt; mbstr;\r\n   }\r\n}<\/pre>\n<p>Another important thing to note here, is that invoking <tt>co_await<\/tt> with a time duration is not possible out of the box. However, it is made possible by overloading the <tt>co_await<\/tt> operator. An implementation that works on Windows is the following:<\/p>\n<pre class=\"lang:c++ decode:true \" >#include &lt;windows.h&gt;\r\n\r\nauto operator co_await(std::chrono::system_clock::duration duration)\r\n{\r\n   class awaiter\r\n   {\r\n      static\r\n         void CALLBACK TimerCallback(PTP_CALLBACK_INSTANCE,\r\n            void* Context,\r\n            PTP_TIMER)\r\n      {\r\n         stdco::coroutine_handle&lt;&gt;::from_address(Context).resume();\r\n      }\r\n      PTP_TIMER timer = nullptr;\r\n      std::chrono::system_clock::duration duration;\r\n   public:\r\n\r\n      explicit awaiter(std::chrono::system_clock::duration d) \r\n         : duration(d)\r\n      {}\r\n\r\n      ~awaiter()\r\n      {\r\n         if (timer) CloseThreadpoolTimer(timer);\r\n      }\r\n\r\n      bool await_ready() const\r\n      {\r\n         return duration.count() &lt;= 0;\r\n      }\r\n\r\n      bool await_suspend(stdco::coroutine_handle&lt;&gt; resume_cb)\r\n      {\r\n         int64_t relative_count = -duration.count();\r\n         timer = CreateThreadpoolTimer(TimerCallback,\r\n            resume_cb.address(),\r\n            nullptr);\r\n         bool success = timer != nullptr;\r\n         SetThreadpoolTimer(timer, (PFILETIME)&amp;relative_count, 0, 0);\r\n         return success;\r\n      }\r\n\r\n      void await_resume() {}\r\n\r\n   };\r\n   return awaiter{ duration };\r\n}<\/pre>\n<p>This implementation has been sourced from the article <a href=\"https:\/\/devblogs.microsoft.com\/cppblog\/coroutines-in-visual-studio-2015-update-1\/\" rel=\"noopener noreferrer\" target=\"_blank\">Coroutines in Visual Studio 2015 \u2013 Update 1<\/a>.<br \/>\nUPDATE: The code has been changed based on the feedback. See the comments section.<\/p>\n<p>To learn more about coroutines see:<\/p>\n<ul>\n<li><a href=\"https:\/\/en.cppreference.com\/w\/cpp\/language\/coroutines\" rel=\"noopener noreferrer\" target=\"_blank\">C++20 Coroutines<\/a><\/li>\n<li><a href=\"https:\/\/luncliff.github.io\/posts\/Exploring-MSVC-Coroutine.html\" rel=\"noopener noreferrer\" target=\"_blank\">Exploring MSVC Coroutine<\/a><\/li>\n<li><a href=\"https:\/\/lewissbaker.github.io\/2017\/09\/25\/coroutine-theory\" rel=\"noopener noreferrer\" target=\"_blank\">Coroutine Theory<\/a><\/li>\n<li><a href=\"https:\/\/lewissbaker.github.io\/2017\/11\/17\/understanding-operator-co-await\" rel=\"noopener noreferrer\" target=\"_blank\">C++ Coroutines: Understanding operator co_await<\/a><\/li>\n<li><a href=\"https:\/\/lewissbaker.github.io\/2018\/09\/05\/understanding-the-promise-type\" rel=\"noopener noreferrer\" target=\"_blank\">C++ Coroutines: Understanding the promise type<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>One of the most important new features in the C++20 is coroutines. A coroutine is a function that has the ability to be suspended and resumed. A function becomes a coroutine if it uses any of the following:<\/p>\n<ul>\n<li>the <tt>co_await<\/tt> operator to suspend execution until resumed<\/li>\n<li>the <tt>co_return<\/tt> keyword to complete execution and optionally return a value<\/li>\n<li>the <tt>co_yield<\/tt> keyword to suspend execution and return a value<\/li>\n<\/ul>\n<p>A coroutine must also have a return type that satisfies some requirements. However, the C++20 standard, only defines a framework for the execution of coroutines, but does not define any coroutine types satisfying such requirements. That means, we need to either write our own or rely on 3rd party libraries for this. In this post, I&#8217;ll show how to write some simple examples using the <a href=\"https:\/\/github.com\/lewissbaker\/cppcoro\/\" rel=\"noopener noreferrer\" target=\"_blank\">cppcoro<\/a> library.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_uag_custom_page_level_css":"","advgb_blocks_editor_width":"","advgb_blocks_columns_visual_guide":"","_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2},"jetpack_post_was_ever_published":false},"categories":[7],"tags":[451,543,626,627],"class_list":["post-3922","post","type-post","status-publish","format-standard","hentry","category-c","tag-c","tag-c20","tag-coroutines","tag-cppcoro"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.3 - aioseo.com -->\n\t<meta name=\"description\" content=\"This article shows several examples for C++20 coroutines using the cppcoro open-source library.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Marius Bancila\"\/>\n\t<meta name=\"keywords\" content=\"c++,c++20,coroutines,cppcoro\" \/>\n\t<link rel=\"canonical\" href=\"https:\/\/mariusbancila.ro\/blog\/2020\/06\/22\/a-cpp20-coroutine-example\/\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.3\" \/>\n\t\t<meta property=\"og:locale\" content=\"en_US\" \/>\n\t\t<meta property=\"og:site_name\" content=\"Marius Bancila&#039;s Blog | About code. Mostly on C++\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"A C++20 coroutine example\" \/>\n\t\t<meta property=\"og:description\" content=\"This article shows several examples for C++20 coroutines using the cppcoro open-source library.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/mariusbancila.ro\/blog\/2020\/06\/22\/a-cpp20-coroutine-example\/\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2020-06-22T09:30:48+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-06-24T07:56:10+00:00\" \/>\n\t\t<meta name=\"twitter:card\" content=\"summary\" \/>\n\t\t<meta name=\"twitter:title\" content=\"A C++20 coroutine example\" \/>\n\t\t<meta name=\"twitter:description\" content=\"This article shows several examples for C++20 coroutines using the cppcoro open-source library.\" \/>\n\t\t<script type=\"application\/ld+json\" class=\"aioseo-schema\">\n\t\t\t{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/2020\\\/06\\\/22\\\/a-cpp20-coroutine-example\\\/#article\",\"name\":\"A C++20 coroutine example\",\"headline\":\"A C++20 coroutine example\",\"author\":{\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/author\\\/admin\\\/#author\"},\"publisher\":{\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/#organization\"},\"image\":{\"@type\":\"ImageObject\",\"url\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/wp-content\\\/uploads\\\/2020\\\/06\\\/time1.png\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/2020\\\/06\\\/22\\\/a-cpp20-coroutine-example\\\/#articleImage\",\"width\":411,\"height\":313},\"datePublished\":\"2020-06-22T11:30:48+02:00\",\"dateModified\":\"2020-06-24T09:56:10+02:00\",\"inLanguage\":\"en-US\",\"commentCount\":8,\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/2020\\\/06\\\/22\\\/a-cpp20-coroutine-example\\\/#webpage\"},\"isPartOf\":{\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/2020\\\/06\\\/22\\\/a-cpp20-coroutine-example\\\/#webpage\"},\"articleSection\":\"C++, C++, c++20, coroutines, cppcoro\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/2020\\\/06\\\/22\\\/a-cpp20-coroutine-example\\\/#breadcrumblist\",\"itemListElement\":[{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/#listItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/category\\\/it\\\/#listItem\",\"name\":\"IT\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/category\\\/it\\\/#listItem\",\"position\":2,\"name\":\"IT\",\"item\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/category\\\/it\\\/\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/category\\\/it\\\/software\\\/#listItem\",\"name\":\"Software\"},\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/#listItem\",\"name\":\"Home\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/category\\\/it\\\/software\\\/#listItem\",\"position\":3,\"name\":\"Software\",\"item\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/category\\\/it\\\/software\\\/\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/category\\\/it\\\/software\\\/c\\\/#listItem\",\"name\":\"C++\"},\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/category\\\/it\\\/#listItem\",\"name\":\"IT\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/category\\\/it\\\/software\\\/c\\\/#listItem\",\"position\":4,\"name\":\"C++\",\"item\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/category\\\/it\\\/software\\\/c\\\/\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/2020\\\/06\\\/22\\\/a-cpp20-coroutine-example\\\/#listItem\",\"name\":\"A C++20 coroutine example\"},\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/category\\\/it\\\/software\\\/#listItem\",\"name\":\"Software\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/2020\\\/06\\\/22\\\/a-cpp20-coroutine-example\\\/#listItem\",\"position\":5,\"name\":\"A C++20 coroutine example\",\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/category\\\/it\\\/software\\\/c\\\/#listItem\",\"name\":\"C++\"}}]},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/#organization\",\"name\":\"Marius Bancila's Blog\",\"description\":\"About code. Mostly on C++\",\"url\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/author\\\/admin\\\/#author\",\"url\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/author\\\/admin\\\/\",\"name\":\"Marius Bancila\",\"image\":{\"@type\":\"ImageObject\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/2020\\\/06\\\/22\\\/a-cpp20-coroutine-example\\\/#authorImage\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/a84dd2831d955c38355ddea55df4df260809b88f36408bc14fd4eab8f7f131c9?s=96&d=mm&r=g\",\"width\":96,\"height\":96,\"caption\":\"Marius Bancila\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/2020\\\/06\\\/22\\\/a-cpp20-coroutine-example\\\/#webpage\",\"url\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/2020\\\/06\\\/22\\\/a-cpp20-coroutine-example\\\/\",\"name\":\"A C++20 coroutine example\",\"description\":\"This article shows several examples for C++20 coroutines using the cppcoro open-source library.\",\"inLanguage\":\"en-US\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/#website\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/2020\\\/06\\\/22\\\/a-cpp20-coroutine-example\\\/#breadcrumblist\"},\"author\":{\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/author\\\/admin\\\/#author\"},\"creator\":{\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/author\\\/admin\\\/#author\"},\"datePublished\":\"2020-06-22T11:30:48+02:00\",\"dateModified\":\"2020-06-24T09:56:10+02:00\"},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/\",\"name\":\"Marius Bancila's Blog\",\"description\":\"About code. Mostly on C++\",\"inLanguage\":\"en-US\",\"publisher\":{\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/#organization\"}}]}\n\t\t<\/script>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"A C++20 coroutine example","description":"This article shows several examples for C++20 coroutines using the cppcoro open-source library.","canonical_url":"https:\/\/mariusbancila.ro\/blog\/2020\/06\/22\/a-cpp20-coroutine-example\/","robots":"max-image-preview:large","keywords":"c++,c++20,coroutines,cppcoro","webmasterTools":{"miscellaneous":""},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/mariusbancila.ro\/blog\/2020\/06\/22\/a-cpp20-coroutine-example\/#article","name":"A C++20 coroutine example","headline":"A C++20 coroutine example","author":{"@id":"https:\/\/mariusbancila.ro\/blog\/author\/admin\/#author"},"publisher":{"@id":"https:\/\/mariusbancila.ro\/blog\/#organization"},"image":{"@type":"ImageObject","url":"https:\/\/mariusbancila.ro\/blog\/wp-content\/uploads\/2020\/06\/time1.png","@id":"https:\/\/mariusbancila.ro\/blog\/2020\/06\/22\/a-cpp20-coroutine-example\/#articleImage","width":411,"height":313},"datePublished":"2020-06-22T11:30:48+02:00","dateModified":"2020-06-24T09:56:10+02:00","inLanguage":"en-US","commentCount":8,"mainEntityOfPage":{"@id":"https:\/\/mariusbancila.ro\/blog\/2020\/06\/22\/a-cpp20-coroutine-example\/#webpage"},"isPartOf":{"@id":"https:\/\/mariusbancila.ro\/blog\/2020\/06\/22\/a-cpp20-coroutine-example\/#webpage"},"articleSection":"C++, C++, c++20, coroutines, cppcoro"},{"@type":"BreadcrumbList","@id":"https:\/\/mariusbancila.ro\/blog\/2020\/06\/22\/a-cpp20-coroutine-example\/#breadcrumblist","itemListElement":[{"@type":"ListItem","@id":"https:\/\/mariusbancila.ro\/blog\/#listItem","position":1,"name":"Home","item":"https:\/\/mariusbancila.ro\/blog\/","nextItem":{"@type":"ListItem","@id":"https:\/\/mariusbancila.ro\/blog\/category\/it\/#listItem","name":"IT"}},{"@type":"ListItem","@id":"https:\/\/mariusbancila.ro\/blog\/category\/it\/#listItem","position":2,"name":"IT","item":"https:\/\/mariusbancila.ro\/blog\/category\/it\/","nextItem":{"@type":"ListItem","@id":"https:\/\/mariusbancila.ro\/blog\/category\/it\/software\/#listItem","name":"Software"},"previousItem":{"@type":"ListItem","@id":"https:\/\/mariusbancila.ro\/blog\/#listItem","name":"Home"}},{"@type":"ListItem","@id":"https:\/\/mariusbancila.ro\/blog\/category\/it\/software\/#listItem","position":3,"name":"Software","item":"https:\/\/mariusbancila.ro\/blog\/category\/it\/software\/","nextItem":{"@type":"ListItem","@id":"https:\/\/mariusbancila.ro\/blog\/category\/it\/software\/c\/#listItem","name":"C++"},"previousItem":{"@type":"ListItem","@id":"https:\/\/mariusbancila.ro\/blog\/category\/it\/#listItem","name":"IT"}},{"@type":"ListItem","@id":"https:\/\/mariusbancila.ro\/blog\/category\/it\/software\/c\/#listItem","position":4,"name":"C++","item":"https:\/\/mariusbancila.ro\/blog\/category\/it\/software\/c\/","nextItem":{"@type":"ListItem","@id":"https:\/\/mariusbancila.ro\/blog\/2020\/06\/22\/a-cpp20-coroutine-example\/#listItem","name":"A C++20 coroutine example"},"previousItem":{"@type":"ListItem","@id":"https:\/\/mariusbancila.ro\/blog\/category\/it\/software\/#listItem","name":"Software"}},{"@type":"ListItem","@id":"https:\/\/mariusbancila.ro\/blog\/2020\/06\/22\/a-cpp20-coroutine-example\/#listItem","position":5,"name":"A C++20 coroutine example","previousItem":{"@type":"ListItem","@id":"https:\/\/mariusbancila.ro\/blog\/category\/it\/software\/c\/#listItem","name":"C++"}}]},{"@type":"Organization","@id":"https:\/\/mariusbancila.ro\/blog\/#organization","name":"Marius Bancila's Blog","description":"About code. Mostly on C++","url":"https:\/\/mariusbancila.ro\/blog\/"},{"@type":"Person","@id":"https:\/\/mariusbancila.ro\/blog\/author\/admin\/#author","url":"https:\/\/mariusbancila.ro\/blog\/author\/admin\/","name":"Marius Bancila","image":{"@type":"ImageObject","@id":"https:\/\/mariusbancila.ro\/blog\/2020\/06\/22\/a-cpp20-coroutine-example\/#authorImage","url":"https:\/\/secure.gravatar.com\/avatar\/a84dd2831d955c38355ddea55df4df260809b88f36408bc14fd4eab8f7f131c9?s=96&d=mm&r=g","width":96,"height":96,"caption":"Marius Bancila"}},{"@type":"WebPage","@id":"https:\/\/mariusbancila.ro\/blog\/2020\/06\/22\/a-cpp20-coroutine-example\/#webpage","url":"https:\/\/mariusbancila.ro\/blog\/2020\/06\/22\/a-cpp20-coroutine-example\/","name":"A C++20 coroutine example","description":"This article shows several examples for C++20 coroutines using the cppcoro open-source library.","inLanguage":"en-US","isPartOf":{"@id":"https:\/\/mariusbancila.ro\/blog\/#website"},"breadcrumb":{"@id":"https:\/\/mariusbancila.ro\/blog\/2020\/06\/22\/a-cpp20-coroutine-example\/#breadcrumblist"},"author":{"@id":"https:\/\/mariusbancila.ro\/blog\/author\/admin\/#author"},"creator":{"@id":"https:\/\/mariusbancila.ro\/blog\/author\/admin\/#author"},"datePublished":"2020-06-22T11:30:48+02:00","dateModified":"2020-06-24T09:56:10+02:00"},{"@type":"WebSite","@id":"https:\/\/mariusbancila.ro\/blog\/#website","url":"https:\/\/mariusbancila.ro\/blog\/","name":"Marius Bancila's Blog","description":"About code. Mostly on C++","inLanguage":"en-US","publisher":{"@id":"https:\/\/mariusbancila.ro\/blog\/#organization"}}]},"og:locale":"en_US","og:site_name":"Marius Bancila's Blog | About code. Mostly on C++","og:type":"article","og:title":"A C++20 coroutine example","og:description":"This article shows several examples for C++20 coroutines using the cppcoro open-source library.","og:url":"https:\/\/mariusbancila.ro\/blog\/2020\/06\/22\/a-cpp20-coroutine-example\/","article:published_time":"2020-06-22T09:30:48+00:00","article:modified_time":"2020-06-24T07:56:10+00:00","twitter:card":"summary","twitter:title":"A C++20 coroutine example","twitter:description":"This article shows several examples for C++20 coroutines using the cppcoro open-source library."},"aioseo_meta_data":{"post_id":"3922","title":"A C++20 coroutine example","description":"This article shows several examples for C++20 coroutines using the cppcoro open-source library.","keywords":[{"label":"C++","value":"C++"},{"label":"C++20","value":"C++20"},{"label":"coroutines","value":"coroutines"},{"label":"cppcoro","value":"cppcoro"}],"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"location":null,"local_seo":null,"breadcrumb_settings":null,"limit_modified_date":false,"ai":null,"created":"2021-03-18 21:02:54","updated":"2025-12-12 07:55:32","seo_analyzer_scan_date":null,"focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"author_meta":{"display_name":"Marius Bancila","author_link":"https:\/\/mariusbancila.ro\/blog\/author\/admin\/"},"featured_img":null,"jetpack_publicize_connections":[],"uagb_featured_image_src":{"full":false,"thumbnail":false,"medium":false,"medium_large":false,"large":false,"1536x1536":false,"2048x2048":false},"uagb_author_info":{"display_name":"Marius Bancila","author_link":"https:\/\/mariusbancila.ro\/blog\/author\/admin\/"},"uagb_comment_info":8,"uagb_excerpt":"One of the most important new features in the C++20 is coroutines. A coroutine is a function that has the ability to be suspended and resumed. A function becomes a coroutine if it uses any of the following: the co_await operator to suspend execution until resumed the co_return keyword to complete execution and optionally return&hellip;","coauthors":[],"tax_additional":{"categories":{"linked":["<a href=\"https:\/\/mariusbancila.ro\/blog\/category\/it\/software\/c\/\" class=\"advgb-post-tax-term\">C++<\/a>"],"unlinked":["<span class=\"advgb-post-tax-term\">C++<\/span>"]},"tags":{"linked":["<a href=\"https:\/\/mariusbancila.ro\/blog\/category\/it\/software\/c\/\" class=\"advgb-post-tax-term\">C++<\/a>","<a href=\"https:\/\/mariusbancila.ro\/blog\/category\/it\/software\/c\/\" class=\"advgb-post-tax-term\">c++20<\/a>","<a href=\"https:\/\/mariusbancila.ro\/blog\/category\/it\/software\/c\/\" class=\"advgb-post-tax-term\">coroutines<\/a>","<a href=\"https:\/\/mariusbancila.ro\/blog\/category\/it\/software\/c\/\" class=\"advgb-post-tax-term\">cppcoro<\/a>"],"unlinked":["<span class=\"advgb-post-tax-term\">C++<\/span>","<span class=\"advgb-post-tax-term\">c++20<\/span>","<span class=\"advgb-post-tax-term\">coroutines<\/span>","<span class=\"advgb-post-tax-term\">cppcoro<\/span>"]}},"comment_count":"8","relative_dates":{"created":"Posted 6 years ago","modified":"Updated 6 years ago"},"absolute_dates":{"created":"Posted on June 22, 2020","modified":"Updated on June 24, 2020"},"absolute_dates_time":{"created":"Posted on June 22, 2020 11:30 am","modified":"Updated on June 24, 2020 9:56 am"},"featured_img_caption":"","series_order":"","jetpack_shortlink":"https:\/\/wp.me\/pYNdv-11g","jetpack_sharing_enabled":true,"jetpack_likes_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/mariusbancila.ro\/blog\/wp-json\/wp\/v2\/posts\/3922","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mariusbancila.ro\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mariusbancila.ro\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mariusbancila.ro\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/mariusbancila.ro\/blog\/wp-json\/wp\/v2\/comments?post=3922"}],"version-history":[{"count":10,"href":"https:\/\/mariusbancila.ro\/blog\/wp-json\/wp\/v2\/posts\/3922\/revisions"}],"predecessor-version":[{"id":3934,"href":"https:\/\/mariusbancila.ro\/blog\/wp-json\/wp\/v2\/posts\/3922\/revisions\/3934"}],"wp:attachment":[{"href":"https:\/\/mariusbancila.ro\/blog\/wp-json\/wp\/v2\/media?parent=3922"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mariusbancila.ro\/blog\/wp-json\/wp\/v2\/categories?post=3922"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mariusbancila.ro\/blog\/wp-json\/wp\/v2\/tags?post=3922"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}