13 template<
typename Src>
18 using storage_type = std::invoke_result_t<Src>;
20 using iterator_category = std::input_iterator_tag;
21 using value_type =
typename std::decay_t<Src>::value_type;
23 using difference_type = std::ptrdiff_t;
24 using pointer = std::add_pointer_t<value_type>;
36 if (!_stor.is_pending() && !_stor.has_value()) {
44 return _is_end == other._is_end;
62 mutable storage_type _stor;
93 template<
typename T, coro_allocator Alloc = std_allocator>
103 class promise_type:
public _details::coro_promise_base<T>,
108 trace::set_class(std::coroutine_handle<promise_type>::from_promise(*
this),
typeid(
generator).name());
111 constexpr trace::suspend_always initial_suspend()
const {
return {};}
113 struct switch_awaiter {
114 static constexpr
bool await_ready() noexcept {
return false;}
115 static constexpr
void await_resume() noexcept {}
117 std::coroutine_handle<> await_suspend(std::coroutine_handle<promise_type> h, std::source_location loc = std::source_location::current()) noexcept {
118 promise_type &
self = h.promise();
123 struct final_switch_awaiter {
124 static constexpr
bool await_ready() noexcept {
return false;}
125 static constexpr
void await_resume() noexcept {}
127 std::coroutine_handle<> await_suspend(std::coroutine_handle<promise_type> h) noexcept {
128 promise_type &
self = h.promise();
148 return this->set_resolved().symmetric_transfer();
152 template<
typename Arg>
153 requires future_constructible<T, Arg>
154 switch_awaiter yield_value(Arg && val) {
155 trace::on_yield(std::coroutine_handle<const promise_type>::from_promise(*
this), val);
156 this->set_value(std::forward<Arg>(val));
159 switch_awaiter yield_value(std::exception_ptr e) {
160 trace::on_yield(std::coroutine_handle<const promise_type>::from_promise(*
this), e);
161 this->set_exception(std::move(e));
165 final_switch_awaiter final_suspend() noexcept {
173 return std::coroutine_handle<const promise_type>::from_promise(*this).done();
176 generator get_return_object() {
return this;}
179 return [
this](
auto promise) -> std::coroutine_handle<> {
180 if (done())
return {};
182 auto h = std::coroutine_handle<promise_type>::from_promise(*
this);
183 trace::awaiting_ref(h, this->fut);
195 return _prom->resume();
207 explicit operator bool()
const {
208 return !_prom->done();
239 operator ident_t()
const {
return std::coroutine_handle<promise_type>::from_promise(*_prom);}
244 static promise_type *cast_promise(X *other) {
245 return static_cast<promise_type *
>(
static_cast<_details::coro_promise_base<T> *
>(other));
248 generator(promise_type *p):_prom(p) {}
252 auto h = std::coroutine_handle<promise_type>::from_promise(*x);
257 template<
typename A, coro_allocator B>
friend class generator;
259 std::unique_ptr<promise_type,deleter> _prom;
264 template<
typename R, coro_allocator Alloc>
270 class fetch_args_tag {};
272 inline constexpr fetch_args_tag fetch_args = {};
305 template<
typename R, coro_allocator Alloc,
typename ... Args>
309 using return_type = R;
311 using arg_type = std::tuple<Args...>;
314 class promise_type:
public _details::coro_promise_base<R>,
319 trace::set_class(std::coroutine_handle<promise_type>::from_promise(*
this),
typeid(
generator).name());
323 constexpr trace::suspend_always initial_suspend()
const {
return {};}
325 struct fetch_arg_awaiter {
327 static constexpr
bool await_ready() noexcept {
return true;}
328 static constexpr
void await_suspend(std::coroutine_handle<>) noexcept {}
329 arg_type &await_resume() noexcept {
return *arg;};
332 struct switch_awaiter {
333 promise_type *
self =
nullptr;
334 static constexpr
bool await_ready() noexcept {
return false;}
335 arg_type &await_resume() noexcept {
return *
self->arg;}
337 CORO_OPT_BARRIER std::coroutine_handle<> await_suspend(std::coroutine_handle<promise_type> h, std::source_location loc = std::source_location::current()) noexcept {
343 struct switch_final_awaiter:
public switch_awaiter {
344 CORO_OPT_BARRIER std::coroutine_handle<> await_suspend(std::coroutine_handle<promise_type> h) noexcept {
345 this->
self = &h.promise();
346 return trace::on_switch(h,this->self->set_resolved().symmetric_transfer(),{});
351 template<
typename Arg>
352 requires future_constructible<R, Arg>
353 switch_awaiter yield_value(Arg && val) {
354 trace::on_yield(std::coroutine_handle<const promise_type>::from_promise(*
this), val);
355 this->set_value(std::forward<Arg>(val));
359 switch_awaiter yield_value(std::exception_ptr e) {
360 LIBCORO_TRACE_YIELD(std::coroutine_handle<const promise_type>::from_promise(*
this),e);
361 this->set_exception(std::move(e));
366 fetch_arg_awaiter yield_value(std::nullptr_t) {
370 fetch_arg_awaiter yield_value(fetch_args_tag) {
374 switch_final_awaiter final_suspend() noexcept {
382 return std::coroutine_handle<const promise_type>::from_promise(*this).done();
385 generator get_return_object() {
return this;}
391 auto h = std::coroutine_handle<promise_type>::from_promise(*
this);
392 trace::awaiting_ref(h, this->fut);
397 std::optional<arg_type> arg;
399 template<
typename ... XArgs>
400 void set_arg(XArgs && ... args) {
401 arg.emplace(std::forward<XArgs>(args)...);
412 explicit operator bool()
const {
413 return !_prom->done();
431 template<
typename ... XArgs>
433 static_assert(std::is_constructible_v<arg_type, XArgs...>);
434 _prom->set_arg(std::forward<XArgs>(args)...);
435 return _prom->resume();
443 static promise_type *cast_promise(X *other) {
444 return static_cast<promise_type *
>(
static_cast<_details::coro_promise_base<R> *
>(other));
447 generator(promise_type *p):_prom(p) {}
451 auto h = std::coroutine_handle<promise_type>::from_promise(*x);
456 template<
typename A, coro_allocator B>
friend class generator;
458 std::unique_ptr<promise_type,deleter> _prom;
inherit this class to include coro_allocator into your promise_type
Contains future value of T, where evaluation is deferred until the value is needed.
Contains future value of T, can be co_awaited in coroutine.
generator(generator< R(Args...), A > &&other)
convert from different allocator
future< R > operator()(XArgs &&... args)
call the generator
generator()=default
object can be default constructed
reference operator*()
retrieve current value
static generator_iterator begin(Src src)
retrieve iterator to generator
static generator_iterator end(Src src)
retrieve end iterator
generator_iterator & operator++()
advance next value
bool operator==(const generator_iterator &other) const
you can only compare with end()
Iterator to access generators.
generator(generator< T, A > &&other)
convert from different allocator
auto end()
retrieve end iterator
generator()=default
object can be default constructed
std::add_lvalue_reference_t< T > reference
reference type
auto begin()
retrieve begin iterator
deferred_future< T > operator()()
call the generator
FutureType * release()
Release the future pointer from the promise object.
Carries reference to future<T>, callable, sets value of an associated future<T>
#define CORO_OPT_BARRIER
marks function which servers as barrier between suspended coroutine and normal code
void resume(std::coroutine_handle<> h) noexcept
Record resumption of an coroutine.
std::coroutine_handle on_switch(std::coroutine_handle<>, std::coroutine_handle<> to, const void *)
Record switch (symmetric transfer) from one coroutine to other.