Commit f7900b6b authored by Tom Niget's avatar Tom Niget

Generator core update

parent 5f506528
...@@ -13,11 +13,44 @@ namespace typon { ...@@ -13,11 +13,44 @@ namespace typon {
* https://github.com/feabhas/coroutines-blog * https://github.com/feabhas/coroutines-blog
*/ */
template <typename T> class Generator { template <typename T> class Generator {
class Promise {
public:
using value_type = T;
class promise_type;
explicit Generator(std::coroutine_handle<promise_type> coroutine) noexcept
: _coroutine(coroutine) {}
Generator(const Generator &) = delete;
Generator &operator=(const Generator &) = delete;
Generator(Generator &&other) noexcept
: _coroutine(std::exchange(other._coroutine, nullptr)) {}
Generator &operator=(Generator other) {
std::swap(_coroutine, other._coroutine);
return *this;
}
~Generator() {
if (_coroutine) {
_coroutine.destroy();
}
}
Task<Generator> async_self() {
co_return std::move(*this);
}
auto operator co_await() && noexcept {
return std::move(async_self().operator co_await());
}
class promise_type {
public: public:
using value_type = std::optional<T>; using value_type = std::optional<T>;
Promise() = default; promise_type() = default;
std::suspend_always initial_suspend() { return {}; } std::suspend_always initial_suspend() { return {}; }
std::suspend_always final_suspend() noexcept { std::suspend_always final_suspend() noexcept {
final = true; final = true;
...@@ -38,7 +71,10 @@ template <typename T> class Generator { ...@@ -38,7 +71,10 @@ template <typename T> class Generator {
void return_void() { this->value = std::nullopt; } void return_void() { this->value = std::nullopt; }
inline Generator get_return_object(); inline Generator<T> get_return_object() noexcept {
return Generator{
std::coroutine_handle<promise_type>::from_promise(*this)};
}
value_type get_value() { return std::move(value); } value_type get_value() { return std::move(value); }
...@@ -52,24 +88,12 @@ template <typename T> class Generator { ...@@ -52,24 +88,12 @@ template <typename T> class Generator {
bool final = false; bool final = false;
}; };
public: promise_type::value_type next() {
using value_type = T; if (_coroutine) {
using promise_type = Promise; if (!_coroutine.promise().finished()) {
_coroutine.resume();
explicit Generator(std::coroutine_handle<Promise> handle) : handle(handle) {}
~Generator() {
if (handle) {
handle.destroy();
}
} }
return _coroutine.promise().get_value();
Promise::value_type next() {
if (handle) {
if (!handle.promise().finished()) {
handle.resume();
}
return handle.promise().get_value();
} else { } else {
return {}; return {};
} }
...@@ -79,7 +103,7 @@ public: ...@@ -79,7 +103,7 @@ public:
class iterator { class iterator {
public: public:
using value_type = Promise::value_type; using value_type = promise_type::value_type;
using difference_type = std::ptrdiff_t; using difference_type = std::ptrdiff_t;
using iterator_category = std::input_iterator_tag; using iterator_category = std::input_iterator_tag;
...@@ -88,34 +112,34 @@ public: ...@@ -88,34 +112,34 @@ public:
value_type operator*() const { value_type operator*() const {
if (generator) { if (generator) {
return generator->handle.promise().get_value(); return generator->_coroutine.promise().get_value();
} }
return {}; return {};
} }
value_type operator->() const { value_type operator->() const {
if (generator) { if (generator) {
return generator->handle.promise().get_value(); return generator->_coroutine.promise().get_value();
} }
return {}; return {};
} }
iterator &operator++() { iterator &operator++() {
if (generator && generator->handle) { if (generator && generator->_coroutine) {
generator->handle.resume(); generator->_coroutine.resume();
} }
return *this; return *this;
} }
iterator &operator++(int) { iterator &operator++(int) {
if (generator && generator->handle) { if (generator && generator->_coroutine) {
generator->handle.resume(); generator->_coroutine.resume();
} }
return *this; return *this;
} }
bool operator==(const end_iterator &) const { bool operator==(const end_iterator &) const {
return generator ? generator->handle.promise().finished() : true; return !generator || generator->_coroutine.promise().finished();
} }
private: private:
...@@ -133,14 +157,9 @@ public: ...@@ -133,14 +157,9 @@ public:
private: private:
end_iterator end_sentinel{}; end_iterator end_sentinel{};
std::coroutine_handle<Promise> handle; std::coroutine_handle<promise_type> _coroutine;
}; };
template <typename T>
inline Generator<T> Generator<T>::Promise::get_return_object() {
return Generator{std::coroutine_handle<Promise>::from_promise(*this)};
}
} // namespace typon } // namespace typon
#endif // TYPON_GENERATOR_HPP #endif // TYPON_GENERATOR_HPP
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment