liblinux++

A hosted C++ runtime without any libc.
git clone git://henryandlizzy.uk/liblinux++
Log | Files | Refs

coro.cpp (2640B)


      1 #include "linux.hpp"
      2 
      3 namespace std
      4 {
      5 
      6 template <typename T, typename... Ts>
      7 struct coroutine_traits
      8 {
      9 	using promise_type = T::promise_type;
     10 };
     11 
     12 template <typename T = void>
     13 struct coroutine_handle {
     14 	static coroutine_handle from_address(void* ptr) noexcept
     15 	{
     16 		return coroutine_handle{ptr};
     17 	}
     18 	static coroutine_handle from_promise(T& promise) noexcept
     19 	{
     20 		return from_address(reinterpret_cast<char*>(&promise) - sizeof(frame));
     21 	}
     22 	void resume() const noexcept {
     23 		assert(fp);
     24 		assert(fp->resume);
     25 		fp->resume(fp);
     26 	}
     27 	void destroy() const noexcept {
     28 		assert(fp);
     29 		assert(fp->destroy);
     30 		fp->destroy(fp);
     31 	}
     32 	bool done() const noexcept
     33 	{
     34 		assert(fp);
     35 		return not fp->resume;
     36 	}
     37 
     38 private:
     39 	struct frame
     40 	{
     41 		void(*resume)(frame*) noexcept;
     42 		void(*destroy)(frame*) noexcept;
     43 	};
     44 
     45 	coroutine_handle(void* ptr) noexcept : fp{reinterpret_cast<frame*>(ptr)} {}
     46 	frame* fp = nullptr;
     47 };
     48 
     49 struct suspend_always
     50 {
     51 	bool await_ready() noexcept { return false; }
     52 	template <typename T> // easier to make this a template method than provide a <void> specialisation to coroutine_handle for now
     53 	void await_suspend(coroutine_handle<T>) noexcept {}
     54 	void await_resume() noexcept {}
     55 };
     56 
     57 struct suspend_never
     58 {
     59 	bool await_ready() noexcept { return true; }
     60 	template <typename T>
     61 	void await_suspend(coroutine_handle<T>) noexcept { __builtin_trap(); }
     62 	void await_resume() noexcept {}
     63 };
     64 
     65 }
     66 
     67 struct task
     68 {
     69 	struct promise_type {
     70 		std::suspend_never initial_suspend() noexcept { return {}; }
     71 		std::suspend_always final_suspend() noexcept { return {}; }
     72 		task get_return_object() noexcept { return {*this}; }
     73 		void unhandled_exception() noexcept {}
     74 		void return_void() noexcept {}
     75 		void* operator new(size_t s, span<char> storage) noexcept {
     76 			assert(s <= storage.size());
     77 			return storage.begin();
     78 		}
     79 		void operator delete(void*, size_t) noexcept {}
     80 	};
     81 
     82 	~task() { h.destroy(); }
     83 	bool done() const noexcept { return h.done(); }
     84 	void resume() const noexcept { h.resume(); }
     85 private:
     86 	friend struct promise_type;
     87 	task(promise_type& p) : h{decltype(h)::from_promise(p)} {}
     88 	std::coroutine_handle<promise_type> h;
     89 };
     90 
     91 task mytask(span<char> /*forwarded to new*/) noexcept
     92 {
     93 	*write(stdout, "mytask: started\n"_sp);
     94 	for (int i = 0; i < 3; ++i)
     95 	{
     96 		co_await std::suspend_always{};
     97 		*write(stdout, "mytask: resumed\n"_sp);
     98 	}
     99 	co_return;
    100 }
    101 
    102 int main()
    103 {
    104 	*write(stdout, "main\n"_sp);
    105 	{
    106 		char memory[56];
    107 		task t = mytask(span{memory});
    108 		*write(stdout, "main: mytask created\n"_sp);
    109 		while (not t.done())
    110 		{
    111 			t.resume();
    112 			*write(stdout, "main: back from resume\n"_sp);
    113 		}
    114 	}
    115 	*write(stdout, "main: mytask destroyed\n"_sp);
    116 }