Modern C++ features

Coroutine

Coroutine can be seem as “functions whose execution you can pause” and later “resumed”. C++ 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.

Co-Routine

C++ 20 supported with following concepts:

  • co_await: to suspend execution until resumed, the arguments for co_await should be awaitable instance, which will be explained later.
1
2
3
4
5
6
7
8
9
task<> tcp_echo_server()
{
    char data[1024];
    while (true)
    {
        std::size_t n = co_await  socket.async_read_some(buffer(data));  //suspend the execution and return to the caller
                        co_await  async_write(socket, buffer(data, n));  //suspend the execution and return to the caller
    }
}
  • co_yeild: to suspend execution while returning a value:
1
2
3
4
5
generator<unsigned int> iota(unsigned int n = 0)
{
    while (true)
        co_yield n++;
}
  • co_yeild: complete execution and returning a value
1
2
3
4
lazy<int> f()
{
    co_return 7;
}

promise in coroutine

Any function is a coroutine if it contains any of ‘co_wait’, ‘co_yield’ or ‘co_return’. For coroutine contains ‘co_wait’, the return type should alias the special promise_type (via using or typedef like in general) to the specific class or struct defined by the user. The aliased specific class is generally called promise, which must implement some of the specific functions used by the caller to control execution of the coroutine . Coroutine submits its result or exception through this promise object.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class coroutine_return_obj

struct my_promise
{
    //should return object that the coroutine returns
    coroutine_return_obj get_return_object() noexcept {
        return coroutine_return_obj { std::coroutine_handle<my_promise>::from_promise(*this) };
    };

    //Called before the co_wait() call.
    std::suspend_never initial_suspend()  const noexcept { return {}; }

    //Called just before the coroutine ends.
    std::suspend_never final_suspend()    const noexcept { return {}; }

    //Called when no co_returned is called at the end.
    void return_void() noexcept {}

     //Called when some exception happens in coroutine.
    void unhandled_exception() noexcept {
        std::cerr << "Unhandled exception caught...\n";
        exit(1);
    }
};



Enjoy Reading This Article?

Here are some more articles you might like to read next:

  • Addressing of GPGPU
  • Discriminative learning vs Generative learning
  • Fundamental Math for Machine Learning