Skip to content

Instantly share code, notes, and snippets.

@anatoly-spb
Created August 2, 2020 08:18
Show Gist options
  • Save anatoly-spb/279e0f8e19d9a191933319aed314febf to your computer and use it in GitHub Desktop.
Save anatoly-spb/279e0f8e19d9a191933319aed314febf to your computer and use it in GitHub Desktop.
co_yield
namespace coyield
{
template<typename T>
struct generator_type
{
struct promise_type;
using coroutine_handle_type = stdco::coroutine_handle<promise_type>;
coroutine_handle_type handle;
generator_type(coroutine_handle_type handle) : handle{ handle }
{
scope_tracer _{ __FUNCSIG__, this };
}
generator_type(generator_type const&) = delete;
generator_type(generator_type&& other) noexcept : handle{ std::move(other.handle) }
{
scope_tracer _{ __FUNCSIG__, this };
other.handle = nullptr;
}
generator_type& operator = (generator_type const&) = delete;
generator_type& operator = (generator_type&& other) noexcept {
handle = other.handle;
other.handle = nullptr;
return *this;
}
~generator_type()
{
scope_tracer _{ __FUNCSIG__, this };
if (handle) handle.destroy();
}
bool move_next()
{
scope_tracer _{ __FUNCSIG__, this };
_.info("Moving to next");
handle.resume();
_.info("Are we done?");
auto still_going = not handle.done();
_.info(still_going ? "There is another" : "We're done");
return still_going;
}
T current_value()
{
scope_tracer _{ __FUNCSIG__, this };
return handle.promise().value;
}
struct promise_type {
T value;
promise_type() : value{ -1 } {
scope_tracer _{ __FUNCSIG__, this };
}
promise_type(tracer param) : value{ } {
scope_tracer _{ __FUNCSIG__, this };
}
~promise_type() {
scope_tracer _{ __FUNCSIG__, this };
}
auto get_return_object() {
scope_tracer _{ __FUNCSIG__, this };
_.info("return generator object");
return generator_type<T>{coroutine_handle_type::from_promise(*this)};
}
auto initial_suspend() {
scope_tracer _{ __FUNCSIG__, this };
_.info("return suspend_always to suspend coroutine before enter into the body");
return stdco::suspend_always{};
}
void yield_value(T v) {
scope_tracer _{ __FUNCSIG__, this };
_.info("yeild value to ", value = v);
}
auto final_suspend() noexcept {
scope_tracer _{ __FUNCSIG__, this };
_.info("return suspend_always to suspend coroutine in final suspension point");
return stdco::suspend_always{};
}
void unhandled_exception() {
scope_tracer _{ __FUNCSIG__, this };
std::terminate();
}
void return_void() {
scope_tracer _{ __FUNCSIG__, this };
_.info("return_void");
}
}; // promise_type
}; // generator_type
generator_type<int> coroutine()
{
scope_tracer _{ __FUNCSIG__ };
_.info("co_yeild 1");
co_yield 1;
_.info("co_yeild 2");
co_yield 2;
_.info("we are done");
}
void test()
{
scope_tracer _{ __FUNCSIG__ };
_.info("generator_type<int> g = coroutine();");
generator_type<int> g = coroutine();
_.info("while(g.move_next()) {");
while (g.move_next()) {
_.info("g.current_value()");
_.info(g.current_value());
}
_.info("}");
}
}
16600 [00000000]>> void __cdecl coyield::test(void)
249400 [00000000] generator_type<int> g = coroutine();
284800 [009A2E98] >> __thiscall coyield::generator_type<int>::promise_type::promise_type(void)
317600 [009A2E98] << __thiscall coyield::generator_type<int>::promise_type::promise_type(void)
346500 [009A2E98] >> auto __thiscall coyield::generator_type<int>::promise_type::get_return_object(void)
378100 [009A2E98] return generator object
411100 [002BFB34] >> __thiscall coyield::generator_type<int>::generator_type(struct std::experimental::coroutine_handle<struct coyie
ld::generator_type<int>::promise_type>)
439600 [002BFB34] << __thiscall coyield::generator_type<int>::generator_type(struct std::experimental::coroutine_handle<struct coyie
ld::generator_type<int>::promise_type>)
471200 [009A2E98] << auto __thiscall coyield::generator_type<int>::promise_type::get_return_object(void)
496800 [009A2E98] >> auto __thiscall coyield::generator_type<int>::promise_type::initial_suspend(void)
526500 [009A2E98] return suspend_always to suspend coroutine before enter into the body
556600 [009A2E98] << auto __thiscall coyield::generator_type<int>::promise_type::initial_suspend(void)
584600 [00000000] while(g.move_next()) {
627300 [002BFB34] >> bool __thiscall coyield::generator_type<int>::move_next(void)
657800 [002BFB34] Moving to next
691100 [00000000] >> struct coyield::generator_type<int> __cdecl coyield::coroutine(void)
724300 [00000000] co_yeild 1
751900 [009A2E98] >> void __thiscall coyield::generator_type<int>::promise_type::yield_value(int)
781400 [009A2E98] yeild value to 1
821800 [009A2E98] << void __thiscall coyield::generator_type<int>::promise_type::yield_value(int)
848700 [002BFB34] Are we done?
873000 [002BFB34] There is another
900000 [002BFB34] << bool __thiscall coyield::generator_type<int>::move_next(void)
931200 [00000000] g.current_value()
956500 [002BFB34] >> int __thiscall coyield::generator_type<int>::current_value(void)
984900 [002BFB34] << int __thiscall coyield::generator_type<int>::current_value(void)
1011900 [00000000] 1
1036900 [002BFB34] >> bool __thiscall coyield::generator_type<int>::move_next(void)
1062000 [002BFB34] Moving to next
1084800 [00000000] co_yeild 2
1107600 [009A2E98] >> void __thiscall coyield::generator_type<int>::promise_type::yield_value(int)
1133000 [009A2E98] yeild value to 2
1176700 [009A2E98] << void __thiscall coyield::generator_type<int>::promise_type::yield_value(int)
1203800 [002BFB34] Are we done?
1226400 [002BFB34] There is another
1248700 [002BFB34] << bool __thiscall coyield::generator_type<int>::move_next(void)
1273700 [00000000] g.current_value()
1296200 [002BFB34] >> int __thiscall coyield::generator_type<int>::current_value(void)
1321500 [002BFB34] << int __thiscall coyield::generator_type<int>::current_value(void)
1346500 [00000000] 2
1369700 [002BFB34] >> bool __thiscall coyield::generator_type<int>::move_next(void)
1394700 [002BFB34] Moving to next
1417200 [00000000] we are done
1440900 [00000000] << struct coyield::generator_type<int> __cdecl coyield::coroutine(void)
1466200 [009A2E98] >> void __thiscall coyield::generator_type<int>::promise_type::return_void(void)
1491100 [009A2E98] return_void
1513200 [009A2E98] << void __thiscall coyield::generator_type<int>::promise_type::return_void(void)
1538200 [009A2E98] >> auto __thiscall coyield::generator_type<int>::promise_type::final_suspend(void) noexcept
1563800 [009A2E98] return suspend_always to suspend coroutine in final suspension point
1590100 [009A2E98] << auto __thiscall coyield::generator_type<int>::promise_type::final_suspend(void) noexcept
1619900 [002BFB34] Are we done?
1642400 [002BFB34] We're done
1664500 [002BFB34] << bool __thiscall coyield::generator_type<int>::move_next(void)
1692700 [00000000] }
1716800 [002BFB34] >> __thiscall coyield::generator_type<int>::~generator_type(void)
1746400 [009A2E98] >> __thiscall coyield::generator_type<int>::promise_type::~promise_type(void)
1777300 [009A2E98] << __thiscall coyield::generator_type<int>::promise_type::~promise_type(void)
1810900 [002BFB34] << __thiscall coyield::generator_type<int>::~generator_type(void)
1837600 [00000000]<< void __cdecl coyield::test(void)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment