Case Study IV: Various Job Workflows
Discuss the job workflow, started in the section about the 'co_await' keyword.
We'll cover the following...
Before I modify the workflow from section co_await
, I want to make the awaiter workflow more transparent.
The transparent awaiter workflow
I added a few output messages to the program we saw previously when discussing co_await
.
#include <coroutine>#include <iostream>struct MySuspendAlways {bool await_ready() const noexcept {std::cout << " MySuspendAlways::await_ready" << '\n';return false;}void await_suspend(std::coroutine_handle<>) const noexcept {std::cout << " MySuspendAlways::await_suspend" << '\n';}void await_resume() const noexcept {std::cout << " MySuspendAlways::await_resume" << '\n';}};struct MySuspendNever {bool await_ready() const noexcept {std::cout << " MySuspendNever::await_ready" << '\n';return true;}void await_suspend(std::coroutine_handle<>) const noexcept {std::cout << " MySuspendNever::await_suspend" << '\n';}void await_resume() const noexcept {std::cout << " MySuspendNever::await_resume" << '\n';}};struct Job {struct promise_type;using handle_type = std::coroutine_handle<promise_type>;handle_type coro;Job(handle_type h): coro(h){}~Job() {if ( coro ) coro.destroy();}void start() {coro.resume();}struct promise_type {auto get_return_object() {return Job{handle_type::from_promise(*this)};}MySuspendAlways initial_suspend() {std::cout << " Job prepared" << '\n';return {};}MySuspendAlways final_suspend() noexcept {std::cout << " Job finished" << '\n';return {};}void unhandled_exception() {}};};Job prepareJob() {co_await MySuspendNever();}int main() {std::cout << "Before job" << '\n';auto job = prepareJob();job.start();std::cout << "After job" << '\n';}
First of all, I replaced the predefined awaitables std::suspend_always and std::suspend_never with my awaitables MySuspendAlways
(line 4) and MySuspendNever
(line 18). I use them in lines 49, 53, and 63. My awaitables mimic the behavior of the predefined awaitables but additionally write a comment. Due to the use of std::cout
, the member functions await_ready
, await_suspend
, and await_resume
cannot be declared as constexpr
.
The function initial_suspend
(line 49) is executed at the beginning of the coroutine and the function final_suspend
at its end (line 53). The call prepareJob()
(line 69) triggers the creation of the coroutine object, and the function call job.start()
its resumption and, hence, completion (line 70 ...