corotask1.hpp

The following code example is taken from the book
C++20 - The Complete Guide by Nicolai M. Josuttis, Leanpub, 2021
The code is licensed under a Creative Commons Attribution 4.0 International License. Creative Commons License


#include <iostream>
#include <coroutine>
#include <exception>  // for terminate()

// handle to deal with a simple coroutine task
// - providing resume() to resume it
class CoroTask {
 public:
  // helper type for state and customization:
  struct promise_type {
    auto get_return_object() {        // create the coroutine handle
      return std::coroutine_handle<promise_type>::from_promise(*this);
    }
    auto initial_suspend() {          // start immediately?
      return std::suspend_always{};   // - suspend immediately
    }
    auto final_suspend() noexcept {   // clean-ups / postprocessing
      return std::suspend_always{};   // - suspend at the end
    }
    void unhandled_exception() {      // deal with exceptions
      std::terminate();               // - terminate the program
    }
    void return_void() {              // deal with the end or with return;
    }
  };

 private:
  // internal handle to allocated state:
  std::coroutine_handle<promise_type> coroHdl;

 public:
  // constructor to initialize the coroutine:
  CoroTask(auto h) : coroHdl{h} {
    std::cout << "- CoroTask: construct\n";
  }
  ~CoroTask() {
    std::cout << "- CoroTask: destruct\n";
    if (coroHdl) {
      coroHdl.destroy();
    }
  }
  // don't copy or move:
  CoroTask(const CoroTask&) = delete;
  CoroTask& operator=(const CoroTask&) = delete;

  // API to resume the coroutine
  // - returns whether there is still something to process
  bool resume() const {
    std::cout << "- CoroTask: resume()\n";
    if (!coroHdl) {
      return false;     // nothing (more) to process
    }
    coroHdl.resume();   // RESUME (just coroHdl() is also possible)
    return !coroHdl.done();
  }
};