11 template<
typename Collectible>
12 class collectible_factory {
14 virtual ~collectible_factory() =
default;
15 virtual Collectible create() = 0;
18 template<
typename Collectible,
typename Fn>
19 class collectible_factory_fn:
public collectible_factory<Collectible> {
21 collectible_factory_fn(Fn &&fn):_fn(std::forward<Fn>(fn)) {}
22 virtual Collectible create() {
return _fn();}
27 template<
typename Collectible,
typename Fn>
28 auto create_collectible_factory(Fn &&fn) {
29 return collectible_factory_fn<Collectible, Fn>(std::forward<Fn>(fn));
43 template<
typename Collectible,
typename Result, coro_allocator Alloc = std_allocator>
47 class promise_type:
public _details::coro_promise<Result> {
49 std::suspend_never initial_suspend()
const noexcept {
return {};}
52 trace::set_class(std::coroutine_handle<promise_type>::from_promise(*
this),
typeid(
collector).name());
55 struct final_awaiter: std::suspend_always {
56 std::coroutine_handle<>
await_suspend(std::coroutine_handle<promise_type> me) noexcept {
57 promise_type &
self = me.promise();
63 final_awaiter final_suspend()
const noexcept {
return {};}
64 collector get_return_object() {
return {
this};}
66 struct yield_awaiter {
68 static constexpr
bool await_ready() noexcept {
return false;}
69 std::coroutine_handle<>
await_suspend(std::coroutine_handle<promise_type> me, std::source_location loc = std::source_location::current()) {
71 return trace::on_switch(me, self->_waiting(
false).symmetric_transfer(),&loc);
73 Collectible await_resume() {
74 return self->_factory->create();
79 yield_awaiter yield_value([[maybe_unused]] X &&x) {
80 trace::on_yield(std::coroutine_handle<const promise_type>::from_promise(*
this),x);
86 if (this->fut != col) {
87 if (this->fut) out = this->set_resolved();
94 auto h =std::coroutine_handle<promise_type>::from_promise(*
this);
95 trace::awaiting_ref(h, _waiting.get_future());
99 std::coroutine_handle<promise_type>::from_promise(*this).destroy();
102 return std::coroutine_handle<const promise_type>::from_promise(*this).done();
105 _details::collectible_factory<Collectible> *_factory;
114 _prom->connect(
this);
125 if (
this != &other) {
126 std::destroy_at(
this);
127 std::construct_at(
this, std::move(other));
140 template<
typename ... Args>
142 static_assert(future_constructible<Collectible, Args ...>);
148 _prom->_waiting = std::move(
promise);
150 if constexpr(
sizeof...(Args) == 1 && (invocable_r_exact<Args, Collectible> && ...)) {
151 [
this](
auto &&arg,
auto &&...) {
152 this->set_factory_resume([&]()->Collectible{
157 this->set_factory_resume([&]{
158 return Collectible(std::forward<Args>(args)...);
164 operator ident_t()
const {
return std::coroutine_handle<promise_type>::from_promise(*_prom);}
168 collector(promise_type *p):_prom(p) {
169 _prom->connect(
this);
173 static promise_type *cast_promise(X *other) {
174 return static_cast<promise_type *
>(
static_cast<_details::coro_promise_base<Result> *
>(other));
184 template<
typename A,
typename B, coro_allocator C>
friend class collector;
186 std::unique_ptr<promise_type,Deleter> _prom;
188 template<
typename Fn>
189 void set_factory_resume(Fn &&fn) {
190 _details::collectible_factory_fn<Collectible, Fn> f(std::forward<Fn>(fn));
191 _prom->_factory = &f;
collector & operator=(collector &&other)
assign by move
future< bool > operator()(Args &&... args)
call collected and push next collectible item
collector(collector &&other)
move
collector()=default
construct uninitalized collector - you can initialize it later by assignment
collector(collector< Collectible, Result, A > &&other)
convert from different allocator
The collector is a reversed generator. The coroutine consumes values and then returns a result.
promise_t get_promise()
Retrieve promise and begin evaluation.
std::coroutine_handle await_suspend(std::coroutine_handle<> h) noexcept
co_await support, called with suspended coroutine
bool await_ready() const noexcept
co_await support, returns true, if value is ready (resolved)
Contains future value of T, can be co_awaited in coroutine.
contains prepared coroutine (prepared to run)
FutureType * release()
Release the future pointer from the promise object.
Carries reference to future<T>, callable, sets value of an associated future<T>
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.