...

/

Case Study II: Variations of Futures

Case Study II: Variations of Futures

Implement a lazy future and a future based on the future in section co_return.

We'll cover the following...

Before I create variations of the future from the section The co_return keyword, we should understand its control flow. Comments make the control flow transparent.

Press + to interact
#include <coroutine>
#include <iostream>
#include <memory>
template<typename T>
struct MyFuture {
std::shared_ptr<T> value;
MyFuture(std::shared_ptr<T> p): value(p) {
std::cout << " MyFuture::MyFuture" << '\n';
}
~MyFuture() {
std::cout << " MyFuture::~MyFuture" << '\n';
}
T get() {
std::cout << " MyFuture::get" << '\n';
return *value;
}
struct promise_type {
std::shared_ptr<T> ptr = std::make_shared<T>();
promise_type() {
std::cout << " promise_type::promise_type" << '\n';
}
~promise_type() {
std::cout << " promise_type::~promise_type" << '\n';
}
MyFuture<T> get_return_object() {
std::cout << " promise_type::get_return_object" << '\n';
return ptr;
}
void return_value(T v) {
std::cout << " promise_type::return_value" << '\n';
*ptr = v;
}
std::suspend_never initial_suspend() {
std::cout << " promise_type::initial_suspend" << '\n';
return {};
}
std::suspend_never final_suspend() noexcept {
std::cout << " promise_type::final_suspend" << '\n';
return {};
}
void unhandled_exception() {
std::exit(1);
}
};
};
MyFuture<int> createFuture() {
std::cout << "createFuture" << '\n';
co_return 2021;
}
int main() {
std::cout << '\n';
auto fut = createFuture();
auto res = fut.get();
std::cout << "res: " << res << '\n';
std::cout << '\n';
}

The comments should make the control flow obvious. The call createFuture (line 57) causes the creation of an instance of MyFuture (line 49). Before MyFuture's constructor call (line 8) is completed, the promise promise_type is created, executed, and destroyed (lines 19 - 47). The promise uses in each step of its control flow the awaitable std::suspend_never (lines 35 and 39) and, hence, never pauses. It must be allocated to save the result of the promise for the later fut.get() call (line 58). Furthermore, the used std::shared_ptrs (lines 7 and 20) ensure that the program does not cause a ...