Skip to content

Instantly share code, notes, and snippets.

@paxbun
Last active December 8, 2020 20:47
Show Gist options
  • Save paxbun/891da6c3b4a098eea94053126ccd599b to your computer and use it in GitHub Desktop.
Save paxbun/891da6c3b4a098eea94053126ccd599b to your computer and use it in GitHub Desktop.
C++20 coroutine example
#include <coroutine>
#include <iostream>
#include <optional>
size_t buffer[22];
struct my_generator
{
struct promise_type
{
int yielded_value = 0;
static void* operator new(size_t mem) noexcept
{
std::cout << "operator new(" << mem << "): " << buffer << std::endl;
if (mem > sizeof buffer) return nullptr;
return buffer;
}
static void operator delete(void* block, size_t mem) noexcept {}
auto get_return_object()
{
return handle_type::from_promise(*this);
}
static my_generator get_return_object_on_allocation_failure()
{
std::cout << "get_return_object_on_allocation_failure" << std::endl;
return my_generator {};
}
auto initial_suspend()
{
return std::suspend_always {};
}
auto final_suspend() noexcept
{
return std::suspend_always {};
}
void return_value(int i)
{
yielded_value = i;
}
auto yield_value(int i)
{
yielded_value = i;
return std::suspend_always {};
}
void unhandled_exception()
{
std::terminate();
}
};
using handle_type = std::coroutine_handle<promise_type>;
handle_type handle;
my_generator(std::nullptr_t = nullptr) {}
my_generator(handle_type handle) : handle { handle } {}
my_generator(const my_generator&) = delete;
my_generator(my_generator&&) = delete;
~my_generator()
{
if (handle) handle.destroy();
}
bool has_next()
{
return handle && !handle.done();
}
int next()
{
if (!handle.done())
{
handle.resume();
auto& promise = handle.promise();
return promise.yielded_value;
}
throw std::runtime_error("generator is closed");
}
};
my_generator fibonacci()
{
int small = 0;
int big = 1;
std::cout << &small << std::endl << &big << std::endl;
co_yield 0;
co_yield 1;
while (true)
{
int new_value = small + big;
co_yield new_value;
small = big;
big = new_value;
}
co_return small + big;
}
my_generator power_of_two()
{
int rtn = 1;
std::cout << &rtn << std::endl;
for (int i = 0; i < 10; ++i)
{
co_yield rtn;
rtn *= 2;
}
co_return rtn;
}
int main()
{
my_generator generator = power_of_two();
while (generator.has_next()) std::cout << generator.next() << std::endl;
my_generator generator2 = fibonacci();
for (int i = 0; i < 20 && generator2.has_next(); ++i)
std::cout << generator2.next() << std::endl;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment