From b7f98de1fab66e26097005b4e8da6f8253660405 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20G=C3=BCndling?= Date: Mon, 15 Jul 2024 08:40:42 +0200 Subject: [PATCH] generator --- include/utl/generator.h | 58 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 include/utl/generator.h diff --git a/include/utl/generator.h b/include/utl/generator.h new file mode 100644 index 0000000..a19bc38 --- /dev/null +++ b/include/utl/generator.h @@ -0,0 +1,58 @@ +#include +#include + +namespace utl { + +template +struct generator { + struct promise_type { + generator get_return_object() { return handle_type::from_promise(*this); } + std::suspend_always initial_suspend() { return {}; } + std::suspend_always final_suspend() noexcept { return {}; } + void unhandled_exception() { exception_ = std::current_exception(); } + + template From> + std::suspend_always yield_value(From&& from) { + value_ = std::forward(from); + return {}; + } + + void return_void() {} + + T value_; + std::exception_ptr exception_; + }; + + using handle_type = std::coroutine_handle; + + generator(handle_type h) : h_(h) {} + + ~generator() { h_.destroy(); } + + explicit operator bool() { + fill(); + return !h_.done(); + } + + T operator()() { + fill(); + full_ = false; + return std::move(h_.promise().value_); + } + +private: + void fill() { + if (!full_) { + h_(); + if (h_.promise().exception_) { + std::rethrow_exception(h_.promise().exception_); + } + full_ = true; + } + } + + handle_type h_; + bool full_{false}; +}; + +} // namespace utl \ No newline at end of file