examples

Toy examples in single C files.
git clone git://henryandlizzy.uk/examples
Log | Files | Refs

coro-state-machine.cpp (2224B)


      1 #include "coroutine_owner.hpp"
      2 
      3 #include <exception>
      4 #include <cassert>
      5 #include <iostream>
      6 
      7 using std::cerr, std::endl;
      8 
      9 struct task
     10 {
     11 	struct promise_type
     12 	{
     13 		task get_return_object() { return make_coroutine_owner(*this); }
     14 		std::suspend_never initial_suspend() { return {}; }
     15 		void return_value(task);
     16 		void unhandled_exception() { std::terminate(); }
     17 		std::suspend_always final_suspend() noexcept { return {}; }
     18 		coroutine_owner<promise_type> continuation;
     19 	};
     20 
     21 	task() = default;
     22 	task(coroutine_owner<promise_type> c)
     23 	:	h{std::move(c)}
     24 	{}
     25 
     26 	coroutine_owner<promise_type> h;
     27 
     28 	struct await_done
     29 	{
     30 		bool await_ready();
     31 		void await_suspend(std::coroutine_handle<> s);
     32 		coroutine_owner<promise_type> await_resume();
     33 		std::coroutine_handle<> awaiting;
     34 		promise_type& promise;
     35 	};
     36 	await_done done() { return {{}, h->promise()}; }
     37 };
     38 
     39 void task::promise_type::return_value(task t) { continuation = std::move(t.h); }
     40 
     41 
     42 bool task::await_done::await_ready()
     43 {
     44 	return false;
     45 }
     46 void task::await_done::await_suspend(std::coroutine_handle<> s)
     47 {
     48 	assert(not awaiting);
     49 	awaiting = s;
     50 }
     51 coroutine_owner<task::promise_type> task::await_done::await_resume()
     52 {
     53 	awaiting = {};
     54 	return std::exchange(promise.continuation, {});
     55 }
     56 
     57 struct awaitable
     58 {
     59 	std::coroutine_handle<> awaiting;
     60 	bool await_ready() { return false; }
     61 	void await_suspend(std::coroutine_handle<> s) { assert(not std::exchange(awaiting, s)); }
     62 	void await_resume() {}
     63 
     64 	void event() {
     65 		std::exchange(awaiting, {}).resume();
     66 	}
     67 };
     68 
     69 task state_machine(awaitable& event);
     70 
     71 task loop_machine(awaitable& event)
     72 {
     73 	cerr << "init loop\n";
     74 	for (unsigned i = 0; i < 3; ++i)
     75 	{
     76 		co_await event;
     77 		cerr << "loop!\n";
     78 	}
     79 	co_return state_machine(event);
     80 }
     81 
     82 task state_machine(awaitable& event)
     83 {
     84 	cerr << "init\n";
     85 	co_await event;
     86 	cerr << "button pressed\n";
     87 	co_await event;
     88 	cerr << "button pressed 2\n";
     89 	co_await event;
     90 	cerr << "button pressed 3\n";
     91 	co_return loop_machine(event);
     92 }
     93 
     94 task state_engine(task t)
     95 {
     96 	cerr << "se init\n";
     97 	for (;;)
     98 		t = task{co_await t.done()};
     99 }
    100 
    101 int main()
    102 {
    103 	awaitable event;
    104 	auto h = state_machine(event);
    105 	auto e = state_engine(std::move(h));
    106 	for (unsigned i = 0; i < 10; ++i)
    107 		event.event();
    108 	cerr << "Done!\n";
    109 }