{"id":1448,"date":"2022-05-27T14:53:33","date_gmt":"2022-05-27T12:53:33","guid":{"rendered":"https:\/\/www.blauringlabs.com\/?p=1448"},"modified":"2023-01-23T18:27:02","modified_gmt":"2023-01-23T17:27:02","slug":"coroutines-in-c20-a-technical-introduction","status":"publish","type":"post","link":"https:\/\/www.blauringlabs.com\/de\/coroutines-in-c20-a-technical-introduction\/","title":{"rendered":"Coroutines in C++20. A technical introduction"},"content":{"rendered":"\n<h1 class=\"wp-block-heading\">Coroutines<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\">Introduction<\/h2>\n\n\n\n<p>A function is like always going to a different bar where you have to tell the waiter what you want, a coroutine is like always going to the same bar and that the waiter already knows what you want.<br>Saves you time and resources.<br>Coroutines are useful when you&#8217;re going to want to run a task repeatedly remembering what happened last time.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">What is a coroutine?<\/h2>\n\n\n\n<p>A coroutine is a function that can suspend execution to be resumed later.<\/p>\n\n\n\n<p>Coroutines are stackless: they suspend execution by returning to the caller and the data that is required to resume execution is stored separately from the stack. This allows for sequential code that executes asynchronously, and also supports algorithms on lazy-computed infinite sequences and other uses.<\/p>\n\n\n\n<p>A function is a coroutine if its definition does any of the following operators: co_return, co_yield amd co_await.<\/p>\n\n\n\n<p>This is not a coroutine, is a normal function which prints &#8222;Hello world&#8220;:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\n    void foo(){\n        std::cout &lt;&lt; &quot;Hello world&quot;;\n    }\n\n    int main() {\n        foo();    \n    }\n<\/pre><\/div>\n\n\n<p>But this is not a coroutine either, it will cause a compile error.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\n    void foo(){\n        co_return &quot;Hello world&quot;; \/\/Neither with co_wait or co_yield\n    }\n\n    int main() {\n        foo();    \n    }\n<\/pre><\/div>\n\n\n<p>Every coroutine must have a return type that satisfies a number of requirements<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Elements of coroutines<\/h2>\n\n\n\n<p>Each coroutine is associated with the promise object, the coroutine handle and the coroutine state.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Promise Object<\/h3>\n\n\n\n<p>This object is manipulated from inside the coroutine. The coroutine submits its result or exception through this object.<br>An example:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\n    struct return_object {\n        struct promise_type {\n            return_object get_return_object() { return {}; }\n            std::suspend_never initial_suspend() { return {}; }\n            std::suspend_never final_suspend() noexcept { return {}; }\n            void unhandled_exception() {}               \n            void return_void(){}\n        };\n    };\n<\/pre><\/div>\n\n\n<p>All the functions inside promise_type are mandatory, let\u00b4s explain each one.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>get_return_object() to obtain the object that is passed back to the caller.<\/li>\n\n\n\n<li>std::suspend_never initial_suspend() the coroutine keeps running until the first suspending co_await. This is the model for \u201chot-start\u201d coroutines which execute synchronously during their construction and don\u2019t return an object until the first suspension inside the function body.<\/li>\n\n\n\n<li>final_suspend after the coroutine function body has finished<br>When a coroutine reaches a suspension point the return object obtained earlier is returned to the caller\/resumer, after implicit conversion to the return type of the coroutine, if necessary.<\/li>\n\n\n\n<li>return_value or return_void to define what the coroutine returns.<\/li>\n\n\n\n<li>if the coroutine ends with an uncaught exception, catches the exception and calls unhandled_exception() from within the catch-block<br> <h3>Coroutine Handle<\/h3> <p>The coroutine handle, manipulated from outside the coroutine. This is used to resume execution of the coroutine or to destroy the coroutine frame.<br>An example:<\/p><\/li>\n<\/ul>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\n    #include &lt;concepts&gt;\n    #include &lt;coroutine&gt;\n    #include &lt;exception&gt;\n    #include &lt;iostream&gt;\n\n    \/\/definition of the return object and the promise type\n    struct return_object {\n        struct promise_type {\n            return_object get_return_object() { return {}; }\n            std::suspend_never initial_suspend() { return {}; }\n            std::suspend_never final_suspend() noexcept { return {}; }\n            void return_void() {}\n            void unhandled_exception() {}\n        };\n    };\n\n    \/\/this is a coroutine, the return type satisfies the requirements and inside is co_return operator.\n    return_object foo()\n    {\n        co_return; \n        \/* destroys all variables with automatic storage duration in reverse order they were created.\n        Calls promise_type.final_suspend() and co_awaits the result *\/           \n    }\n\n    int main()\n    {\n        \/\/we create a handle of type coroutine_handle\n        std::coroutine_handle&lt;&gt; handle;            \n        \/\/this coroutine do nothing\n        foo();\n        \/\/we can manipulate the hanlde from outside the coroutine\n        handle.resume();\n        handle.destroy();\n    }\n\n<\/pre><\/div>\n\n\n<p>The hanlde is like a pointer to the coroutine state, so we can change the value of any parameter in that state and the handle will remain the same. To do that we will use co_await but first we need to understand the coroutine states.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Coroutine state<\/h3>\n\n\n\n<p>The coroutine state is an internal heap-allocated object that contains:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>the promise object<\/li>\n\n\n\n<li>the parameters<\/li>\n\n\n\n<li>the current suspension point<\/li>\n\n\n\n<li>local variables whose lifetime spans the current suspension point<br>\n<h2>co_await<\/h2>\n<p>The unary operator co_await suspends a coroutine and returns control to the caller.<\/p>\n<h3>Awaitable object<\/h3>\n<p>We must use the expression &#8222;co_await expr;&#8220; where &#8222;expr&#8220; is the awaitable object or awaiter. The awaiter has three methods:<\/p>\n<\/li>\n\n\n\n<li>await_ready is an optimization, if it returns true, then co_await does not suspend the function. The header provides two pre-defined awaiters, std::suspend_always and std::suspend_never. As their names imply, suspend_always::await_ready always returns false, while suspend_never::await_ready always returns true.<\/li>\n\n\n\n<li>await_suspend Store the coroutine handle every time await_suspend is called.<\/li>\n\n\n\n<li>await_resume returns the value of the co_await expression.<\/li>\n<\/ul>\n\n\n\n<p>An example:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\n   \n    \/\/definition of the return object and the promise type\n    struct return_object {\n        struct promise_type {\n            return_object get_return_object() { return {}; }\n            std::suspend_never initial_suspend() { return {}; }\n            std::suspend_never final_suspend() noexcept { return {}; }\n            void return_void() {}\n            void unhandled_exception() {}\n        };\n    };\n\n    struct awaiter {\n        std::coroutine_handle&lt;&gt; *handle_;\n        constexpr bool await_ready() const noexcept { return false; }\n        void await_suspend(std::coroutine_handle&lt;&gt; handle) { *handle_ = handle; }\n        constexpr void await_resume() const noexcept {}\n    };\n\n    \/\/Coroutine using co_await\n    return_object foo(std::coroutine_handle&lt;&gt; *handle)\n    {\n            int fib1 = 0;\n            int fib2 = 1;\n            \/\/pass the handler to the await_suspend method\n            awaiter wait{handle};\n            for (int i = 0;; ++i) {\n                    co_await wait; \/\/suspends the coroutine and returns control to the caller.\n                    std::cout &lt;&lt; fib1 &lt;&lt; &quot;, &quot; &lt;&lt; fib2 &lt;&lt; &quot;, &quot;;\n                    fib1 = fib2 + fib1; \n                    fib2 = fib2 + fib1;               \n            }          \n    }\n\n    int main()\n    {\n            \/\/we create a handle of type coroutine_handle\n            std::coroutine_handle&lt;&gt; handle;            \n            \/\/pass the control of the handler to foo\n            foo(&amp;handle);\n            std::cout &lt;&lt; &quot;Fibonacci: &quot;;\n            for (int i = 1; i &lt; 11; ++i) {\n                    handle();\n            }\n            \/\/To avoid leaking memory, destroy coroutine state \n            handle.destroy();\n    }\n<\/pre><\/div>\n\n\n<p>This is the output:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n    Fibonacci: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, \n    233, 377, 610, 987, 1597, 2584, 4181,\n<\/pre><\/div>\n\n\n<p>You can avoid to use the awaitable by creating the handle in the return_object and returning it to the caller using the get_return_object method from promise_type.<br>An example:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\n   \n\n    struct return_object {\n            struct promise_type {\n                    return_object get_return_object() {\n                            return {\n                              \/\/return the handle\n                              .handle_ = std::coroutine_handle::from_promise(*this)\n                            };\n                    }\n                    std::suspend_never initial_suspend() { return {}; }\n                    std::suspend_never final_suspend() noexcept { return {}; }\n                    void unhandled_exception() {}\n            };\n            \/\/create the handle\n            std::coroutine_handle handle_;\n            operator std::coroutine_handle() const { return handle_; }\n            operator std::coroutine_handle&lt;&gt;() const { return handle_; }\n    };\n\n    return_object foo()\n    {\n            int fib1 = 0;\n            int fib2 = 1;\n            std::cout &lt;&lt; &quot;Fibonacci: &quot;;\n            for (int i = 0;; ++i) {\n                    co_await std::suspend_always{}; \n                    std::cout &lt;&lt; fib1 &lt;&lt; &quot;, &quot; &lt;&lt; fib2 &lt;&lt; &quot;, &quot;;\n                    fib1 = fib2 + fib1; \n                    fib2 = fib2 + fib1;               \n            }            \n    }\n\n    int main()\n    {\n            \/\/we create a pointer to a handle\n            std::coroutine_handle&lt;&gt; handle = foo();  \n            for (int i = 1; i &lt; 11; ++i) {\n                     handle();\n            }\n            handle.destroy();        \n    }\n<\/pre><\/div>\n\n\n<p>This is the output:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n    Fibonacci: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, \n    144, 233, 377, 610, 987, 1597, 2584, 4181,\n<\/pre><\/div>\n\n\n<h3 class=\"wp-block-heading\">Transmit info<\/h3>\n\n\n\n<p>What we did till now is to pass the control from the caller to the coroutine but we can send just the info in the promise object to main by changing the handle.<br>An example:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\n    template\n    struct awaiter {\n            \/\/we will send the promise oject in place of the handle\n            promise_object *promise_;\n            bool await_ready() { return false; }\n            bool await_suspend(std::coroutine_handle handle) {\n                    promise_ = &amp;handle.promise();\n                    return false; \/\/to don\u00b4t suspend the coroutine \n                                     \/\/till the promise is set in the coroutine.   \n            }\n            promise *await_resume() { return promise_; }\n    };\n\n    struct return_object {\n            struct promise_type {\n                    \/\/add something to send, the value is set in the coroutine\n                    std::string message;\n                    return_object get_return_object() {\n                            return {\n                               .handle_ = std::coroutine_handle::from_promise(*this)\n                            };\n                    }\n                    std::suspend_never initial_suspend() { return {}; }\n                    std::suspend_never final_suspend() noexcept { return {}; }\n                    void unhandled_exception() {}\n            };\n            std::coroutine_handle handle_;\n            operator std::coroutine_handle() const { return handle_; }\n    };\n\n    \/\/Coroutine using co_await\n    return_object foo()\n    {\n            auto pointer_promise = co_await awaiter{};\n            int fib1 = 0;\n            int fib2 = 1;\n            std::cout &lt;&lt; &quot;Fibonacci: &quot;;\n            for (int i = 0;; ++i) {\n               pointer_promise-&gt;message = std::to_string(fib1) + &quot;, &quot; \\\n                                                        + std::to_string(fib2) + &quot;, &quot;;\n                    co_await std::suspend_always{}; \n                    fib1 = fib2 + fib1; \n                    fib2 = fib2 + fib1;               \n            }          \n    }\n\n    int main()\n    {\n            \/\/create a pointer to a handle\n            std::coroutine_handle handle = foo();\n            \/\/from this pointer handle only need the promise object\n            return_object::promise_type &amp;promise = handle.promise();        \n            for (int i = 1; i &lt; 11; ++i) {\n                    \/\/print the promise param that we set in the coroutine                                                                        \n                    std::cout &lt;&lt; promise.message;\n                    handle();\n            }\n            handle.destroy();\n    }\n<\/pre><\/div>\n\n\n<p>This is the output:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n    Fibonacci: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181,\n<\/pre><\/div>\n\n\n<h2 class=\"wp-block-heading\">co_yield<\/h2>\n\n\n\n<p>Suspend execution returning a value, so using co_yeild, we can simplify the previous example by adding a yield_value method to the promise_type inside our return object.<br>An example:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\n  \n    struct return_object {\n            struct promise_type {\n                    std::string message;\n                    return_object get_return_object() {\n                            return {\n                                    .handle_ = std::coroutine_handle::from_promise(*this)\n                            };\n                    }\n                    std::suspend_never initial_suspend() { return {}; }\n                    std::suspend_never final_suspend() noexcept { return {}; }\n                    void unhandled_exception() {}\n                    \/\/by addding this method we can modify the promise_object values to transmit\n                    std::suspend_always yield_value(auto value) {\n                            \/\/store in message the value passed by co_yield\n                            message = value;\n                            return {};\n                    }\n            };\n            std::coroutine_handle handle_;\n    };\n\n    \/\/Coroutine using co_yield\n    return_object foo()\n    {\n            int fib1 = 0;\n            int fib2 = 1;\n            std::cout &lt;&lt; &quot;Fibonacci: &quot;;\n            for (int i = 0;; ++i) {\n                    auto value = std::to_string(fib1) + &quot;, &quot; + std::to_string(fib2) + &quot;, &quot;;\n                    fib1 = fib2 + fib1; \n                    fib2 = fib2 + fib1;  \n                    co_yield value;             \n            }          \n    }\n\n    int main()\n    {\n            auto handle = foo().handle_;        \n            auto &amp;promise = handle.promise();       \n            for (int i = 1; i &lt; 11; ++i) {\n                    std::cout &lt;&lt; promise.message;\n                    handle();\n            }\n            handle.destroy();\n    } \n<\/pre><\/div>\n\n\n<p>This is the output:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n    Fibonacci: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181,\n<\/pre><\/div>\n\n\n<h2 class=\"wp-block-heading\">co_return<\/h2>\n\n\n\n<p>co_return signal the end of a coroutine, there are three ways for a coroutine to signal that it is complete:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u201cco_return value;\u201d to return a final value.<\/li>\n\n\n\n<li>\u201cco_return;\u201d to end the coroutine without a final value.<\/li>\n\n\n\n<li>let execution fall off the end of the function.<\/li>\n<\/ul>\n\n\n\n<p>An example:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\n    \n\n    struct return_object {\n            struct promise_type {\n                    std::string message;\n                    return_object get_return_object() {\n                            return {\n                                    .handle_ = std::coroutine_handle::from_promise(*this)\n                            };\n                    }\n                    std::suspend_never initial_suspend() { return {}; }\n                    std::suspend_always final_suspend() noexcept { return {}; }\n                    void unhandled_exception() {}\n                    std::suspend_always return_value(auto value) {\n                            \/\/the value passed with co_return is stored in message\n                            message = value;\n                            return {};\n                    }\n            };\n            std::coroutine_handle handle_;\n    };\n\n    \/\/Coroutine using co_return\n    return_object foo()\n    {\n            int fib1 = 0;\n            int fib2 = 1;\n            std::string message = &quot;&quot;;\n            for (int i = 1; i&lt;11; ++i) {\n                    auto value = std::to_string(fib1) + &quot;, &quot; + std::to_string(fib2) + &quot;, &quot;;\n                    fib1 = fib2 + fib1; \n                    fib2 = fib2 + fib1;  \n                    message = message + value;          \n            }\n            co_return message;             \n    }\n\n    int main()\n    {\n            auto handle = foo().handle_;     \n            \/\/at this point coroutin is suspended at its final suspend point,        \n            std::cout &lt;&lt; handle.done() &lt;&lt; std::endl;    \n            auto &amp;promise = handle.promise();       \n            std::cout &lt;&lt; &quot;Fibonacci: &quot;;\n            std::cout &lt;&lt; promise.message &lt;&lt; std::endl;    \n            handle.destroy();\n    }\n<\/pre><\/div>\n\n\n<p>This is the output:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n    Fibonacci: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181,\n<\/pre><\/div>\n\n\n<h1 class=\"wp-block-heading\">Comparation<\/h1>\n\n\n\n<p>In a normal cpp function we need to store the numbers in an array and in each iteration pass the array and the index to a function. When the function returns the memory still being used.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\n    void foo(int index, int fibo&#x5B;]){\n            if (index == 0)\n                    fibo&#x5B;index] = 0;\n            else if (index == 1)\n                    fibo&#x5B;index] = 1;\n            else\n                    fibo&#x5B;index] = fibo&#x5B;index - 1] + fibo&#x5B;index - 2];\n    }\n\n    int main() {\n            int n = 20;\n            int fibo&#x5B;n];\n            int index = 0;\n            while (index &lt; n) {\n                    foo(index, fibo); \n                    index++;\n            }\n            cout &lt;&lt; &quot;Fibonacci :&quot;;\n            for (int i = 0; i &lt; n; i++)\n            cout &lt;&lt; fibo&#x5B;i] &lt;&lt; &quot;  &quot;;\n    }\n<\/pre><\/div>\n\n\n<p>This is the output:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n    Fibonacci: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181,    \n<\/pre><\/div>\n\n\n<p>As we so in the previous examples, with a coroutine we don\u00b4t need this number of variables and to send it each time. In case of the coroutines, when the task finish the memory is released.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Example<\/h2>\n\n\n\n<p>In the next example we will code to produce a state machine with the next state diagram<br><img decoding=\"async\" src=\"https:\/\/www.blauringlabs.com\/wp-content\/uploads\/168548172-f7707d87-1ce0-42d2-af53-876060ad5893.png\" alt=\"Diagrama en blanco (2)\"><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Code<\/h3>\n\n\n\n<p>Add some libraries<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\n     #include &lt;coroutine&gt;\n     #include &lt;iostream&gt;\n     #include &lt;stdlib.h&gt;\n     #include &lt;math.h&gt;\n<\/pre><\/div>\n\n\n<p>Define the states. As we don\u00b4t have any sensor we declare an extra state, standby, to have an infinite while loop and create a new simulated sensor values each time goes to start state.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n    enum State { start, cooling, heating, charging, finish, standby};\n    static const char *enum_str&#x5B;] = { &quot;Start&quot;, &quot;Cooling&quot;, &quot;Heating&quot;, &quot;charging&quot;, &quot;Finish&quot;, &quot;StandBy&quot; };\n<\/pre><\/div>\n\n\n<p>Create a struct message to the data that the coroutine should return to the caller<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\n    struct message {\n            double temperature;\n            double batteryCharge;\n            State state;\n    };\n<\/pre><\/div>\n\n\n<p>Next code is for the return_object type<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\n    struct return_object {\n            struct promise_type {\n                    message info;\n                            return_object get_return_object() {\n                                    return {\n                                    .handle_ = std::coroutine_handle::from_promise(*this)\n                            };\n                    }\n                    std::suspend_never initial_suspend() { return {}; }\n                    std::suspend_always final_suspend() noexcept { return {}; }\n                    void unhandled_exception() {}\n                    std::suspend_always yield_value(message value) {\n                            info = value;\n                            return {};\n                    }\n                    std::suspend_always return_value(message value) {\n                            info = value;\n                            return {};\n                    }\n            };\n            std::coroutine_handle handle_;\n    };\n<\/pre><\/div>\n\n\n<p>Now we create a coroutine to manage the cooling and heating states transitions.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\n    return_object acclimate(message info){\n            if(info.batteryCharge&gt;20){\n                    while(info.temperature &gt; 20 and info.batteryCharge&gt;20){   \n                            info.temperature = info.temperature - 0.1; \n                            \/*as we haven\u00b4t any real battery this code simulates a battery discharge while cooling*\/\n                            info.batteryCharge = info.batteryCharge - 0.8;\n                            info.state = cooling;\n                            co_yield info;\n                    }\n                    while(info.temperature &lt; 18 and info.batteryCharge&gt;20){\n                            info.temperature = info.temperature + 0.1; \n                            \/*as we haven\u00b4t any real battery this code simulates a battery discharge while heating*\/\n                            info.batteryCharge = info.batteryCharge - 0.8;\n                            info.state = heating;\n                            co_yield info;\n                    }\n                    if(info.temperature&lt;=20 or info.temperature&gt;=18){            \n                            info.state = charging;\n                            co_yield info;\n                    }\n            }else{        \n                    info.state = charging;\n                    co_yield info;\n            }\n    }\n<\/pre><\/div>\n\n\n<p>Define a second coroutine to manage the battery charge.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\n    return_object charger(message info){    \n            while(info.batteryCharge&lt;94.9){\n                    info.batteryCharge = info.batteryCharge + 0.1;\n                    \/*as we haven\u00b4t any real sensor this code simulates a change of temperature while battery is charging*\/\n                    info.temperature = info.temperature + 0.01;\n            }\n            co_return info;\n    }\n<\/pre><\/div>\n\n\n<p>As we haven\u00b4t any real sensor we need to simulate new temperature values and the same for the battery charge state. Once we got those values we manage the first state flow. For that we code te next<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\n    void init_values(message *p_info){\n            p_info-&gt;temperature = rand() % 55;\n            p_info-&gt;batteryCharge = rand() % 100;\n            if(p_info-&gt;temperature&lt;18 and p_info-&gt;batteryCharge&gt;20){\n                    p_info-&gt;state = heating;\n                    std::cout &lt;&lt; &quot;The actual temperature is &quot; + std::to_string(p_info-&gt;temperature) + &quot;. Heating at &quot; + std::to_string(p_info-&gt;batteryCharge) + &quot;% of battery.&quot; &lt;&lt; std::endl;             \n            }else if(p_info-&gt;temperature&gt;20 and p_info-&gt;batteryCharge&gt;20){\n                    p_info-&gt;state = cooling;   \n                    std::cout &lt;&lt; &quot;The actual temperature is &quot; + std::to_string(p_info-&gt;temperature) + &quot;. Cooling at &quot; + std::to_string(p_info-&gt;batteryCharge) + &quot;% of battery.&quot; &lt;&lt; std::endl;                 \n            }else{\n                    if(p_info-&gt;batteryCharge&gt;20){\n                            p_info-&gt;state = finish;\n                    }else{                                                                                                                  \n                            p_info-&gt;state = charging;\n                    }\n            }\n    }\n<\/pre><\/div>\n\n\n<p>At last, our main function where we call the coroutines and define the states funcionalities.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\n    int main(){   \n\n        message info;\n        info.state = start;\n        message* p_info = nullptr;\n        p_info = &amp;info; \n\n        std::coroutine_handle handle;                 \n        return_object::promise_type* promise;\n        std::coroutine_handle handle2;                \n        return_object::promise_type* promise2; \n\n        while(info.state != 5){\n            switch (info.state) {\n            case start:       \n                std::cout &lt;&lt; &quot;Start a new sequence&quot; &lt;&lt; std::endl;\n                init_values(p_info);\n                handle = acclimate(info).handle_;\n                promise = &amp;handle.promise();\n                break;\n            case cooling:  \n                handle();\n                info = promise-&gt;info;\n                break;\n            case heating:    \n                handle();\n                info = promise-&gt;info;\n                break;\n            case finish:         \n                std::cout &lt;&lt; &quot;The actual temperature is &quot; + std::to_string(info.temperature) + &quot;. &quot; + enum_str&#x5B;info.state] + &quot; at &quot; + std::to_string(info.batteryCharge) + &quot;% of battery.&quot; &lt;&lt; std::endl;           \n                info.state = start; \n                break;\n            case charging:\n                std::cout &lt;&lt; &quot;The actual temperature is &quot; + std::to_string(info.temperature) + &quot;. Start &quot; + enum_str&#x5B;info.state] + &quot; at &quot; + std::to_string(info.batteryCharge) + &quot;% of battery.&quot; &lt;&lt; std::endl; \n                handle2 = charger(info).handle_;                  \n                promise2 = &amp;handle2.promise();            \n                info = promise2-&gt;info;\n                std::cout &lt;&lt; &quot;The actual temperature is &quot; + std::to_string(info.temperature) + &quot;. Finish &quot; + enum_str&#x5B;charging] + &quot; at &quot; + std::to_string(info.batteryCharge) + &quot;% of battery.&quot; &lt;&lt; std::endl;             \n                if(info.temperature&lt;18){ \n                    handle = acclimate(info).handle_;  \n                    promise = &amp;handle.promise();               \n                    info = promise-&gt;info;\n                    info.state = heating;\n                    std::cout &lt;&lt; &quot;The actual temperature is &quot; + std::to_string(info.temperature) + &quot;. &quot; + enum_str&#x5B;info.state] + &quot; at &quot; + std::to_string(info.batteryCharge) + &quot;% of battery.&quot; &lt;&lt; std::endl; \n                }else if(info.temperature&gt;20){  \n                    handle = acclimate(info).handle_;                \n                    promise = &amp;handle.promise();              \n                    info.state = cooling;  \n                    std::cout &lt;&lt; &quot;The actual temperature is &quot; + std::to_string(info.temperature) + &quot;. &quot; + enum_str&#x5B;info.state] + &quot; at &quot; + std::to_string(info.batteryCharge) + &quot;% of battery.&quot; &lt;&lt; std::endl; \n                }else{\n                    info.state = finish;\n                }\n                break;\n            }\n        }\n    }       \n<\/pre><\/div>\n\n\n<p>Output:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n    Start a new sequence\n    The actual temperature is 28.00. Cooling at 86.00% of battery.\n    The actual temperature is 20.00. Start charging at 22.00% of battery.\n    The actual temperature is 27.30. Finish charging at 95.00% of battery.\n    The actual temperature is 27.30. Cooling at 95.00% of battery.\n    The actual temperature is 19.90. Start charging at 35.80% of battery.\n    The actual temperature is 25.82. Finish charging at 95.00% of battery.\n    The actual temperature is 25.82. Cooling at 95.00% of battery.\n    The actual temperature is 19.92. Start charging at 47.80% of battery.\n    The actual temperature is 24.64. Finish charging at 95.00% of battery.\n    The actual temperature is 24.64. Cooling at 95.00% of battery.\n    The actual temperature is 19.94. Start charging at 57.40% of battery.\n    The actual temperature is 23.70. Finish charging at 95.00% of battery.\n    The actual temperature is 23.70. Cooling at 95.00% of battery.\n    The actual temperature is 19.90. Start charging at 64.60% of battery.\n    The actual temperature is 22.94. Finish charging at 95.00% of battery.\n    The actual temperature is 22.94. Cooling at 95.00% of battery.\n    The actual temperature is 19.94. Start charging at 71.00% of battery.\n    The actual temperature is 22.34. Finish charging at 95.00% of battery.\n    The actual temperature is 22.34. Cooling at 95.00% of battery.\n    The actual temperature is 19.94. Start charging at 75.80% of battery.\n    The actual temperature is 21.86. Finish charging at 95.00% of battery.\n    The actual temperature is 21.86. Cooling at 95.00% of battery.\n    The actual temperature is 19.96. Start charging at 79.80% of battery.\n    The actual temperature is 21.48. Finish charging at 95.00% of battery.\n    The actual temperature is 21.48. Cooling at 95.00% of battery.\n    The actual temperature is 19.98. Start charging at 83.00% of battery.\n    The actual temperature is 21.18. Finish charging at 95.00% of battery.\n    The actual temperature is 21.18. Cooling at 95.00% of battery.\n    The actual temperature is 19.98. Start charging at 85.40% of battery.\n    The actual temperature is 20.94. Finish charging at 95.00% of battery.\n    The actual temperature is 20.94. Cooling at 95.00% of battery.\n    The actual temperature is 19.94. Start charging at 87.00% of battery.\n    The actual temperature is 20.74. Finish charging at 95.00% of battery.\n    The actual temperature is 20.74. Cooling at 95.00% of battery.\n    The actual temperature is 19.94. Start charging at 88.60% of battery.\n    The actual temperature is 20.58. Finish charging at 95.00% of battery.\n    The actual temperature is 20.58. Cooling at 95.00% of battery.\n    The actual temperature is 19.98. Start charging at 90.20% of battery.\n    The actual temperature is 20.46. Finish charging% of battery.\n    The actual temperature is 20.46. Cooling at 95.00% of battery.\n    The actual temperature is 19.96. Start charging at 91.00% of battery.\n    The actual temperature is 20.36. Finish charging at 95.00% of battery.\n    The actual temperature is 20.36. Cooling at 95.00% of battery.\n    The actual temperature is 19.96. Start charging at 91.80% of battery.\n    The actual temperature is 20.28. Finish charging at 95.00% of battery.\n    The actual temperature is 20.28. Cooling at 95.00% of battery.\n    The actual temperature is 19.98. Start charging at 92.60% of battery.\n    The actual temperature is 20.22. Finish charging at 95.00% of battery.\n    The actual temperature is 20.22. Cooling at 95.00% of battery.\n    The actual temperature is 19.92. Start charging at 92.60% of battery.\n    The actual temperature is 20.16. Finish charging at 95.00% of battery.\n    The actual temperature is 20.16. Cooling at 95.00% of battery.\n    The actual temperature is 19.96. Start charging at 93.40% of battery.\n    The actual temperature is 20.12. Finish charging at 95.00% of battery.\n    The actual temperature is 20.12. Cooling at 95.00% of battery.\n    The actual temperature is 19.92. Start charging at 93.40% of battery.\n    The actual temperature is 20.08. Finish charging at 95.00% of battery.\n    The actual temperature is 20.08. Cooling at 95.00% of battery.\n    The actual temperature is 19.98. Start charging at 94.20% of battery.\n    The actual temperature is 20.06. Finish charging at 95.00% of battery.\n    The actual temperature is 20.06. Cooling at 95.00% of battery.\n    The actual temperature is 19.96. Start charging at 94.20% of battery.\n    The actual temperature is 20.04. Finish charging at 95.00% of battery.\n    The actual temperature is 20.04. Cooling at 95.00% of battery.\n    The actual temperature is 19.94. Start charging at 94.20% of battery.\n    The actual temperature is 20.02. Finish charging at 95.00% of battery.\n    The actual temperature is 20.02. Cooling at 95.00% of battery.\n    The actual temperature is 19.92. Cooling at 94.20% of battery.\n    The actual temperature is 20.00. Finish charging at 95.00% of battery.\n    The actual temperature is 20.00. Cooling at 95.00% of battery.\n    The actual temperature is 19.90. Start charging at 94.20% of battery.\n    The actual temperature is 19.98. Finish charging at 95.00% of battery.\n    The actual temperature is 19.98. Finish at 95.00% of battery.\n<\/pre><\/div>\n\n\n<h2 class=\"wp-block-heading\">Compiler<\/h2>\n\n\n\n<p>Use compiler explorer or gcc 11.2 or older. Use the next flags -std=c++20 and -fcoroutines<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Example<\/h2>\n\n\n\n<p>01- <a href=\"https:\/\/en.cppreference.com\/w\/cpp\/language\/coroutines\">https:\/\/en.cppreference.com\/w\/cpp\/language\/coroutines<\/a><\/p>\n\n\n\n<p>02- <a href=\"https:\/\/www.scs.stanford.edu\/~dm\/blog\/c++-coroutines.html\">https:\/\/www.scs.stanford.edu\/~dm\/blog\/c++-coroutines.html<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Coroutines Introduction A function is like always going to a different bar where you have to tell the waiter what you want, a coroutine is like always going to the same bar and that the waiter already knows\u2026<\/p>\n","protected":false},"author":2,"featured_media":1482,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"pgc_meta":"","footnotes":""},"categories":[18,17],"tags":[],"class_list":["post-1448","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-c","category-development"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.blauringlabs.com\/de\/wp-json\/wp\/v2\/posts\/1448","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.blauringlabs.com\/de\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.blauringlabs.com\/de\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.blauringlabs.com\/de\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.blauringlabs.com\/de\/wp-json\/wp\/v2\/comments?post=1448"}],"version-history":[{"count":15,"href":"https:\/\/www.blauringlabs.com\/de\/wp-json\/wp\/v2\/posts\/1448\/revisions"}],"predecessor-version":[{"id":1490,"href":"https:\/\/www.blauringlabs.com\/de\/wp-json\/wp\/v2\/posts\/1448\/revisions\/1490"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.blauringlabs.com\/de\/wp-json\/wp\/v2\/media\/1482"}],"wp:attachment":[{"href":"https:\/\/www.blauringlabs.com\/de\/wp-json\/wp\/v2\/media?parent=1448"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.blauringlabs.com\/de\/wp-json\/wp\/v2\/categories?post=1448"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.blauringlabs.com\/de\/wp-json\/wp\/v2\/tags?post=1448"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}