Coroutines are a relatively new feature in C++, introduced in C++20, that enable a function to be executed in a non-blocking manner, allowing it to be paused and resumed at specific points during its execution. Coroutines are useful for asynchronous programming, where a function can be called and then allow the program to continue executing while the function is performing its work in the background.
A coroutine is defined using the co_await and co_yield keywords, which allow the function to pause and resume execution at specific points. The co_await keyword is used to pause execution and wait for an asynchronous operation to complete, while the co_yield keyword is used to return a value and pause execution until the coroutine is resumed.
Here’s an example of a coroutine that generates Fibonacci numbers:
#include <iostream>
#include <experimental/coroutine>
class fibonacci {
public:
class iterator {
public:
int operator*() const { return value_; }
iterator& operator++() {
int temp = value_;
value_ += last_;
last_ = temp;
return *this;
}
bool operator==(const iterator& other) const {
return value_ == other.value_;
}
bool operator!=(const iterator& other) const {
return !(*this == other);
}
std::experimental::coroutine_handle<> coro_;
private:
int value_ = 1;
int last_ = 0;
};
iterator begin() {
return { std::experimental::coroutine_handle<>::from_address(&coroutine_) };
}
iterator end() { return {}; }
private:
friend class iterator;
std::experimental::coroutine_handle<> coroutine_ = nullptr;
};
fibonacci::iterator fibonacci::iterator::operator++() {
if (value_ < 0) {
return *this;
}
if (coro_.done()) {
value_ = -1;
return *this;
}
coro_.resume();
if (coro_.done()) {
value_ = -1;
}
return *this;
}
std::experimental::coroutine_handle<> fibonacci_coroutine_handle = nullptr;
fibonacci fibonacci_coroutine() {
int value = 1;
int last = 0;
while (true) {
co_yield value;
int temp = value;
value += last;
last = temp;
}
}
int main() {
fibonacci_coroutine_handle = fibonacci_coroutine().begin().coro_;
for (auto value : fibonacci()) {
std::cout << value << " ";
if (value > 100) {
fibonacci_coroutine_handle.destroy();
break;
}
}
return 0;
}
In this example, the fibonacci_coroutine function is defined as a coroutine using the co_yield keyword to return each Fibonacci number in the sequence. The begin function of the fibonacci class creates an iterator that points to the coroutine, and the operator++ function resumes the coroutine and retrieves the next value from it. When the coroutine is done generating values, it returns -1 to indicate that the sequence has ended.
The main function creates a new fibonacci object and iterates over its values using a range-based for loop. When the value exceeds 100, the coroutine is destroyed using its handle, which stops it from generating any more values.
Overall, coroutines provide a powerful tool for asynchronous programming in C++, allowing functions to be executed in a non-blocking manner and pausing and resuming execution at specific points.