{"id":8628,"date":"2023-11-20T10:44:09","date_gmt":"2023-11-20T10:44:09","guid":{"rendered":"https:\/\/www.modernescpp.com\/?p=8628"},"modified":"2023-11-22T18:19:26","modified_gmt":"2023-11-22T18:19:26","slug":"coroutines-a-scheduler-for-tasks-by-dian-lun-li","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/coroutines-a-scheduler-for-tasks-by-dian-lun-li\/","title":{"rendered":"Coroutines: A Scheduler for Tasks by Dian-Lun Lin"},"content":{"rendered":"\n<p>The last post &#8220;<a href=\"https:\/\/www.modernescpp.com\/index.php\/a-concise-introduction-to-coroutines-by-dian-lun-li\/\" data-type=\"link\" data-id=\"https:\/\/www.modernescpp.com\/index.php\/a-concise-introduction-to-coroutines-by-dian-lun-li\/\">A Concise Introduction to Coroutines by Dian-Lun Lin<\/a>&#8221;  provide the theory. Today, Dian-Lun presents his single-threaded scheduler for C++ coroutines.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1030\" height=\"369\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/11\/TimelineCpp20-1030x369.png\" alt=\"\" class=\"wp-image-8607\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/11\/TimelineCpp20-1030x369.png 1030w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/11\/TimelineCpp20-300x108.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/11\/TimelineCpp20-768x275.png 768w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/11\/TimelineCpp20-705x253.png 705w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/11\/TimelineCpp20.png 1068w\" sizes=\"auto, (max-width: 1030px) 100vw, 1030px\" \/><\/figure>\n\n\n\n<p>This post assumes you are familiar with the previous post &#8220;<a href=\"https:\/\/www.modernescpp.com\/index.php\/a-concise-introduction-to-coroutines-by-dian-lun-li\/\" data-type=\"link\" data-id=\"https:\/\/www.modernescpp.com\/index.php\/a-concise-introduction-to-coroutines-by-dian-lun-li\/\">A Concise Introduction to Coroutines by Dian-Lun Lin<\/a>&#8220;.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">A Single-threaded Scheduler for C++ Coroutines<\/h2>\n\n\n\n<p>In this section, I implement a single-threaded scheduler to schedule coroutines. Let\u2019s begin with the interface:<\/p>\n\n\n\n<!-- HTML generated using hilite.me --><div style=\"background: #f0f3f3; overflow:auto;width:auto;gray;border-width:.1em .1em .1em .8em\"><pre style=\"margin: 0; line-height: 125%\">Task <span style=\"color: #CC00FF\">TaskA<\/span>(Scheduler<span style=\"color: #555555\">&amp;<\/span> sch) {\n  std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&quot;Hello from TaskA<\/span><span style=\"color: #CC3300; font-weight: bold\">\\n<\/span><span style=\"color: #CC3300\">&quot;<\/span>;\n  co_await sch.suspend();\n  std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&quot;Executing the TaskA<\/span><span style=\"color: #CC3300; font-weight: bold\">\\n<\/span><span style=\"color: #CC3300\">&quot;<\/span>;\n  co_await sch.suspend();\n  std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&quot;TaskA is finished<\/span><span style=\"color: #CC3300; font-weight: bold\">\\n<\/span><span style=\"color: #CC3300\">&quot;<\/span>;\n}\n\nTask <span style=\"color: #CC00FF\">TaskB<\/span>(Scheduler<span style=\"color: #555555\">&amp;<\/span> sch) {\n  std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&quot;Hello from TaskB<\/span><span style=\"color: #CC3300; font-weight: bold\">\\n<\/span><span style=\"color: #CC3300\">&quot;<\/span>;\n  co_await sch.suspend();\n  std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&quot;Executing the TaskB<\/span><span style=\"color: #CC3300; font-weight: bold\">\\n<\/span><span style=\"color: #CC3300\">&quot;<\/span>;\n  co_await sch.suspend();\n  std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&quot;TaskB is finished<\/span><span style=\"color: #CC3300; font-weight: bold\">\\n<\/span><span style=\"color: #CC3300\">&quot;<\/span>;\n}\n\n\n<span style=\"color: #007788; font-weight: bold\">int<\/span> <span style=\"color: #CC00FF\">main<\/span>() {\n\n  Scheduler sch;\n\n  sch.emplace(TaskA(sch).get_handle());\n  sch.emplace(TaskB(sch).get_handle());\n\n  std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&quot;Start scheduling...<\/span><span style=\"color: #CC3300; font-weight: bold\">\\n<\/span><span style=\"color: #CC3300\">&quot;<\/span>;\n\n  sch.schedule();\n<\/pre><\/div>\n\n\n\n<p>Both <code>TaskA <\/code>and <code>TaskB <\/code>are coroutines. I construct a scheduler in the main function and place the two tasks (coroutine handles) into the scheduler. I then call <code>schedule <\/code>to schedule the two tasks. A task is a coroutine object that is defined as follows:<\/p>\n\n\n\n<!-- HTML generated using hilite.me --><div style=\"background: #f0f3f3; overflow:auto;width:auto;gray;border-width:.1em .1em .1em .8em\"><pre style=\"margin: 0; line-height: 125%\"><span style=\"color: #006699; font-weight: bold\">struct<\/span> Task {\n\n  <span style=\"color: #006699; font-weight: bold\">struct<\/span> promise_type {\n    std<span style=\"color: #555555\">::<\/span>suspend_always initial_suspend() noexcept { <span style=\"color: #006699; font-weight: bold\">return<\/span> {}; }\n    std<span style=\"color: #555555\">::<\/span>suspend_always final_suspend() noexcept { <span style=\"color: #006699; font-weight: bold\">return<\/span> {}; }\n\n    Task get_return_object() { \n        <span style=\"color: #006699; font-weight: bold\">return<\/span> std<span style=\"color: #555555\">::<\/span>coroutine_handle<span style=\"color: #555555\">&lt;<\/span>promise_type<span style=\"color: #555555\">&gt;::<\/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_void() {}\n    <span style=\"color: #007788; font-weight: bold\">void<\/span> unhandled_exception() {}\n  };\n\n  Task(std<span style=\"color: #555555\">::<\/span>coroutine_handle<span style=\"color: #555555\">&lt;<\/span>promise_type<span style=\"color: #555555\">&gt;<\/span> handle)<span style=\"color: #555555\">:<\/span> handle{handle} {}\n\n  <span style=\"color: #006699; font-weight: bold\">auto<\/span> get_handle() { <span style=\"color: #006699; font-weight: bold\">return<\/span> handle; }\n\n  std<span style=\"color: #555555\">::<\/span>coroutine_handle<span style=\"color: #555555\">&lt;<\/span>promise_type<span style=\"color: #555555\">&gt;<\/span> handle;\n};\n<\/pre><\/div>\n\n\n\n<p>Note that I return <code>std::suspend_always<\/code> in both <code>initial_suspend <\/code>and <code>final_suspend <\/code>functions. This is because I want to hand the entire coroutine execution over to the scheduler. Coroutines are executed only after I call <code>schedule<\/code>. The scheduler is defined as follows:<\/p>\n\n\n\n<!-- HTML generated using hilite.me --><div style=\"background: #f0f3f3; overflow:auto;width:auto;gray;border-width:.1em .1em .1em .8em\"><pre style=\"margin: 0; line-height: 125%\"><span style=\"color: #006699; font-weight: bold\">class<\/span> <span style=\"color: #00AA88; font-weight: bold\">Scheduler<\/span> {\n\n  <span style=\"color: #0099FF; font-style: italic\">\/\/std::queue&lt;std::coroutine_handle&lt;&gt;&gt; _tasks;<\/span>\n  std<span style=\"color: #555555\">::<\/span>stack<span style=\"color: #555555\">&lt;<\/span>std<span style=\"color: #555555\">::<\/span>coroutine_handle<span style=\"color: #555555\">&lt;&gt;&gt;<\/span> _tasks;\n\n  <span style=\"color: #9999FF\">public:<\/span> \n\n    <span style=\"color: #007788; font-weight: bold\">void<\/span> <span style=\"color: #CC00FF\">emplace<\/span>(std<span style=\"color: #555555\">::<\/span>coroutine_handle<span style=\"color: #555555\">&lt;&gt;<\/span> task) {\n      _tasks.push(task);\n    }\n\n    <span style=\"color: #007788; font-weight: bold\">void<\/span> <span style=\"color: #CC00FF\">schedule<\/span>() {\n      <span style=\"color: #006699; font-weight: bold\">while<\/span>(<span style=\"color: #555555\">!<\/span>_tasks.empty()) {\n        <span style=\"color: #0099FF; font-style: italic\">\/\/auto task = _tasks.front();<\/span>\n        <span style=\"color: #006699; font-weight: bold\">auto<\/span> task <span style=\"color: #555555\">=<\/span> _tasks.top();\n        _tasks.pop();\n        task.resume();\n\n        <span style=\"color: #006699; font-weight: bold\">if<\/span>(<span style=\"color: #555555\">!<\/span>task.done()) { \n          _tasks.push(task);\n        }\n        <span style=\"color: #006699; font-weight: bold\">else<\/span> {\n          task.destroy();\n        }\n      }\n    }\n\n    <span style=\"color: #006699; font-weight: bold\">auto<\/span> <span style=\"color: #CC00FF\">suspend<\/span>() {\n      <span style=\"color: #006699; font-weight: bold\">return<\/span> std<span style=\"color: #555555\">::<\/span>suspend_always{};\n    }\n};\n<\/pre><\/div>\n\n\n\n<p>In the scheduler, I store tasks into a stack. I implement <code>emplace <\/code>method to allow users to push a task into the stack. In <code>schedule <\/code>method, I keep popping a task from the stack. After resuming a task, I check if that task is done. If not, I push the task back to the stack for later scheduling. Otherwise, I destroy the finished task. After executing the program, the results are the following:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"400\" height=\"329\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/11\/stackScheduler.png\" alt=\"\" class=\"wp-image-8637\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/11\/stackScheduler.png 400w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/11\/stackScheduler-300x247.png 300w\" sizes=\"auto, (max-width: 400px) 100vw, 400px\" \/><\/figure>\n\n\n\n<p>The scheduler stores tasks using a stack (last in, first out). Interestingly, if I replace the stack with the queue (first in, first out), the execution results become:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"362\" height=\"331\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/11\/queueScheduler.png\" alt=\"\" class=\"wp-image-8638\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/11\/queueScheduler.png 362w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/11\/queueScheduler-300x274.png 300w\" sizes=\"auto, (max-width: 362px) 100vw, 362px\" \/><\/figure>\n\n\n\n<p>For completeness, here are both programs:<\/p>\n\n\n\n<!-- HTML generated using hilite.me --><div style=\"background: #f0f3f3; overflow:auto;width:auto;gray;border-width:.1em .1em .1em .8em\"><pre style=\"margin: 0; line-height: 125%\"><span style=\"color: #0099FF; font-style: italic\">\/\/ stackScheduler.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;stack&gt;<\/span>\n\n\n<span style=\"color: #006699; font-weight: bold\">struct<\/span> Task {\n\n  <span style=\"color: #006699; font-weight: bold\">struct<\/span> promise_type {\n    std<span style=\"color: #555555\">::<\/span>suspend_always initial_suspend() noexcept { <span style=\"color: #006699; font-weight: bold\">return<\/span> {}; }\n    std<span style=\"color: #555555\">::<\/span>suspend_always final_suspend() noexcept { <span style=\"color: #006699; font-weight: bold\">return<\/span> {}; }\n\n    Task get_return_object() { \n        <span style=\"color: #006699; font-weight: bold\">return<\/span> std<span style=\"color: #555555\">::<\/span>coroutine_handle<span style=\"color: #555555\">&lt;<\/span>promise_type<span style=\"color: #555555\">&gt;::<\/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_void() {}\n    <span style=\"color: #007788; font-weight: bold\">void<\/span> unhandled_exception() {}\n  };\n\n  Task(std<span style=\"color: #555555\">::<\/span>coroutine_handle<span style=\"color: #555555\">&lt;<\/span>promise_type<span style=\"color: #555555\">&gt;<\/span> handle)<span style=\"color: #555555\">:<\/span> handle{handle} {}\n\n  <span style=\"color: #006699; font-weight: bold\">auto<\/span> get_handle() { <span style=\"color: #006699; font-weight: bold\">return<\/span> handle; }\n\n  std<span style=\"color: #555555\">::<\/span>coroutine_handle<span style=\"color: #555555\">&lt;<\/span>promise_type<span style=\"color: #555555\">&gt;<\/span> handle;\n};\n\n<span style=\"color: #006699; font-weight: bold\">class<\/span> <span style=\"color: #00AA88; font-weight: bold\">Scheduler<\/span> {\n\n  std<span style=\"color: #555555\">::<\/span>stack<span style=\"color: #555555\">&lt;<\/span>std<span style=\"color: #555555\">::<\/span>coroutine_handle<span style=\"color: #555555\">&lt;&gt;&gt;<\/span> _tasks;\n\n  <span style=\"color: #9999FF\">public:<\/span> \n\n    <span style=\"color: #007788; font-weight: bold\">void<\/span> <span style=\"color: #CC00FF\">emplace<\/span>(std<span style=\"color: #555555\">::<\/span>coroutine_handle<span style=\"color: #555555\">&lt;&gt;<\/span> task) {\n      _tasks.push(task);\n    }\n\n    <span style=\"color: #007788; font-weight: bold\">void<\/span> <span style=\"color: #CC00FF\">schedule<\/span>() {\n      <span style=\"color: #006699; font-weight: bold\">while<\/span>(<span style=\"color: #555555\">!<\/span>_tasks.empty()) {\n        <span style=\"color: #006699; font-weight: bold\">auto<\/span> task <span style=\"color: #555555\">=<\/span> _tasks.top();\n        _tasks.pop();\n        task.resume();\n\n        <span style=\"color: #006699; font-weight: bold\">if<\/span>(<span style=\"color: #555555\">!<\/span>task.done()) { \n          _tasks.push(task);\n        }\n        <span style=\"color: #006699; font-weight: bold\">else<\/span> {\n          task.destroy();\n        }\n      }\n    }\n\n    <span style=\"color: #006699; font-weight: bold\">auto<\/span> <span style=\"color: #CC00FF\">suspend<\/span>() {\n      <span style=\"color: #006699; font-weight: bold\">return<\/span> std<span style=\"color: #555555\">::<\/span>suspend_always{};\n    }\n};\n\n\nTask <span style=\"color: #CC00FF\">TaskA<\/span>(Scheduler<span style=\"color: #555555\">&amp;<\/span> sch) {\n  std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&quot;Hello from TaskA<\/span><span style=\"color: #CC3300; font-weight: bold\">\\n<\/span><span style=\"color: #CC3300\">&quot;<\/span>;\n  co_await sch.suspend();\n  std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&quot;Executing the TaskA<\/span><span style=\"color: #CC3300; font-weight: bold\">\\n<\/span><span style=\"color: #CC3300\">&quot;<\/span>;\n  co_await sch.suspend();\n  std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&quot;TaskA is finished<\/span><span style=\"color: #CC3300; font-weight: bold\">\\n<\/span><span style=\"color: #CC3300\">&quot;<\/span>;\n}\n\nTask <span style=\"color: #CC00FF\">TaskB<\/span>(Scheduler<span style=\"color: #555555\">&amp;<\/span> sch) {\n  std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&quot;Hello from TaskB<\/span><span style=\"color: #CC3300; font-weight: bold\">\\n<\/span><span style=\"color: #CC3300\">&quot;<\/span>;\n  co_await sch.suspend();\n  std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&quot;Executing the TaskB<\/span><span style=\"color: #CC3300; font-weight: bold\">\\n<\/span><span style=\"color: #CC3300\">&quot;<\/span>;\n  co_await sch.suspend();\n  std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&quot;TaskB is finished<\/span><span style=\"color: #CC3300; font-weight: bold\">\\n<\/span><span style=\"color: #CC3300\">&quot;<\/span>;\n}\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\">&#39;\\n&#39;<\/span>;\n\n  Scheduler sch;\n\n  sch.emplace(TaskA(sch).get_handle());\n  sch.emplace(TaskB(sch).get_handle());\n\n  std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&quot;Start scheduling...<\/span><span style=\"color: #CC3300; font-weight: bold\">\\n<\/span><span style=\"color: #CC3300\">&quot;<\/span>;\n\n  sch.schedule();\n\n  std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&#39;\\n&#39;<\/span>;\n\n}\n<\/pre><\/div>\n\n\n\n<!-- HTML generated using hilite.me --><div style=\"background: #f0f3f3; overflow:auto;width:auto;gray;border-width:.1em .1em .1em .8em\"><pre style=\"margin: 0; line-height: 125%\"><span style=\"color: #0099FF; font-style: italic\">\/\/ queueScheduler.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;queue&gt;<\/span>\n\n\n<span style=\"color: #006699; font-weight: bold\">struct<\/span> Task {\n\n  <span style=\"color: #006699; font-weight: bold\">struct<\/span> promise_type {\n    std<span style=\"color: #555555\">::<\/span>suspend_always initial_suspend() noexcept { <span style=\"color: #006699; font-weight: bold\">return<\/span> {}; }\n    std<span style=\"color: #555555\">::<\/span>suspend_always final_suspend() noexcept { <span style=\"color: #006699; font-weight: bold\">return<\/span> {}; }\n\n    Task get_return_object() { \n        <span style=\"color: #006699; font-weight: bold\">return<\/span> std<span style=\"color: #555555\">::<\/span>coroutine_handle<span style=\"color: #555555\">&lt;<\/span>promise_type<span style=\"color: #555555\">&gt;::<\/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_void() {}\n    <span style=\"color: #007788; font-weight: bold\">void<\/span> unhandled_exception() {}\n  };\n\n  Task(std<span style=\"color: #555555\">::<\/span>coroutine_handle<span style=\"color: #555555\">&lt;<\/span>promise_type<span style=\"color: #555555\">&gt;<\/span> handle)<span style=\"color: #555555\">:<\/span> handle{handle} {}\n\n  <span style=\"color: #006699; font-weight: bold\">auto<\/span> get_handle() { <span style=\"color: #006699; font-weight: bold\">return<\/span> handle; }\n\n  std<span style=\"color: #555555\">::<\/span>coroutine_handle<span style=\"color: #555555\">&lt;<\/span>promise_type<span style=\"color: #555555\">&gt;<\/span> handle;\n};\n\n<span style=\"color: #006699; font-weight: bold\">class<\/span> <span style=\"color: #00AA88; font-weight: bold\">Scheduler<\/span> {\n\n  std<span style=\"color: #555555\">::<\/span>queue<span style=\"color: #555555\">&lt;<\/span>std<span style=\"color: #555555\">::<\/span>coroutine_handle<span style=\"color: #555555\">&lt;&gt;&gt;<\/span> _tasks;\n\n  <span style=\"color: #9999FF\">public:<\/span> \n\n    <span style=\"color: #007788; font-weight: bold\">void<\/span> <span style=\"color: #CC00FF\">emplace<\/span>(std<span style=\"color: #555555\">::<\/span>coroutine_handle<span style=\"color: #555555\">&lt;&gt;<\/span> task) {\n      _tasks.push(task);\n    }\n\n    <span style=\"color: #007788; font-weight: bold\">void<\/span> <span style=\"color: #CC00FF\">schedule<\/span>() {\n      <span style=\"color: #006699; font-weight: bold\">while<\/span>(<span style=\"color: #555555\">!<\/span>_tasks.empty()) {\n        <span style=\"color: #006699; font-weight: bold\">auto<\/span> task <span style=\"color: #555555\">=<\/span> _tasks.front();\n        _tasks.pop();\n        task.resume();\n\n        <span style=\"color: #006699; font-weight: bold\">if<\/span>(<span style=\"color: #555555\">!<\/span>task.done()) { \n          _tasks.push(task);\n        }\n        <span style=\"color: #006699; font-weight: bold\">else<\/span> {\n          task.destroy();\n        }\n      }\n    }\n\n    <span style=\"color: #006699; font-weight: bold\">auto<\/span> <span style=\"color: #CC00FF\">suspend<\/span>() {\n      <span style=\"color: #006699; font-weight: bold\">return<\/span> std<span style=\"color: #555555\">::<\/span>suspend_always{};\n    }\n};\n\n\nTask <span style=\"color: #CC00FF\">TaskA<\/span>(Scheduler<span style=\"color: #555555\">&amp;<\/span> sch) {\n  std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&quot;Hello from TaskA<\/span><span style=\"color: #CC3300; font-weight: bold\">\\n<\/span><span style=\"color: #CC3300\">&quot;<\/span>;\n  co_await sch.suspend();\n  std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&quot;Executing the TaskA<\/span><span style=\"color: #CC3300; font-weight: bold\">\\n<\/span><span style=\"color: #CC3300\">&quot;<\/span>;\n  co_await sch.suspend();\n  std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&quot;TaskA is finished<\/span><span style=\"color: #CC3300; font-weight: bold\">\\n<\/span><span style=\"color: #CC3300\">&quot;<\/span>;\n}\n\nTask <span style=\"color: #CC00FF\">TaskB<\/span>(Scheduler<span style=\"color: #555555\">&amp;<\/span> sch) {\n  std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&quot;Hello from TaskB<\/span><span style=\"color: #CC3300; font-weight: bold\">\\n<\/span><span style=\"color: #CC3300\">&quot;<\/span>;\n  co_await sch.suspend();\n  std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&quot;Executing the TaskB<\/span><span style=\"color: #CC3300; font-weight: bold\">\\n<\/span><span style=\"color: #CC3300\">&quot;<\/span>;\n  co_await sch.suspend();\n  std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&quot;TaskB is finished<\/span><span style=\"color: #CC3300; font-weight: bold\">\\n<\/span><span style=\"color: #CC3300\">&quot;<\/span>;\n}\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\">&#39;\\n&#39;<\/span>;\n\n  Scheduler sch;\n\n  sch.emplace(TaskA(sch).get_handle());\n  sch.emplace(TaskB(sch).get_handle());\n\n  std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&quot;Start scheduling...<\/span><span style=\"color: #CC3300; font-weight: bold\">\\n<\/span><span style=\"color: #CC3300\">&quot;<\/span>;\n\n  sch.schedule();\n\n  std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&#39;\\n&#39;<\/span>;\n\n}\n<\/pre><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">What&#8217;s Next?<\/h2>\n\n\n\n<p>This blog post from  Dian-Lun Lin showed a straightforward scheduler for coroutines. I use Dian-Lun&#8217;s scheduler in my next post for further experiments.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The last post &#8220;A Concise Introduction to Coroutines by Dian-Lun Lin&#8221; provide the theory. Today, Dian-Lun presents his single-threaded scheduler for C++ coroutines. This post assumes you are familiar with the previous post &#8220;A Concise Introduction to Coroutines by Dian-Lun Lin&#8220;. A Single-threaded Scheduler for C++ Coroutines In this section, I implement a single-threaded scheduler [&hellip;]<\/p>\n","protected":false},"author":21,"featured_media":8607,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[375],"tags":[445],"class_list":["post-8628","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\/8628","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=8628"}],"version-history":[{"count":15,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/8628\/revisions"}],"predecessor-version":[{"id":8740,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/8628\/revisions\/8740"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media\/8607"}],"wp:attachment":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media?parent=8628"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=8628"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=8628"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}