5#include <libcopp/utils/config/libcopp_build_features.h>
15#if defined(LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR) && LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR
27#if defined(LIBCOPP_MACRO_ENABLE_STD_COROUTINE) && LIBCOPP_MACRO_ENABLE_STD_COROUTINE
29LIBCOPP_COPP_NAMESPACE_BEGIN
31enum class generator_vtable_type : uint8_t {
37template <
class TCONTEXT, generator_vtable_type VTABLE_TYPE = generator_vtable_type::kDefault>
38class LIBCOPP_COPP_API_HEAD_ONLY generator_vtable;
40template <
class TCONTEXT, generator_vtable_type VTABLE_TYPE = generator_vtable_type::kDefault>
41struct LIBCOPP_COPP_API_HEAD_ONLY generator_vtable_type_trait;
43template <
class TVALUE>
44class LIBCOPP_COPP_API_HEAD_ONLY generator_context_base;
46template <
class TVALUE,
class TERROR_TRANSFORM,
bool RETURN_VOID>
47class LIBCOPP_COPP_API_HEAD_ONLY generator_context_delegate;
49template <
class TVALUE,
class TERROR_TRANSFORM>
50class LIBCOPP_COPP_API_HEAD_ONLY generator_context;
52template <
class TVALUE,
class TERROR_TRANSFORM = promise_error_transform<TVALUE>,
53 generator_vtable_type VTABLE_TYPE = generator_vtable_type::kDefault>
54class LIBCOPP_COPP_API_HEAD_ONLY generator_future;
56template <
class TPROMISE,
bool RETURN_VOID, generator_vtable_type VTABLE_TYPE>
57class LIBCOPP_COPP_API_HEAD_ONLY generator_awaitable;
59template <
class TVALUE,
class TERROR_TRANSFORM = promise_error_transform<TVALUE>>
60using generator_lightweight_future = generator_future<TVALUE, TERROR_TRANSFORM, generator_vtable_type::kLightWeight>;
62template <
class TVALUE,
class TERROR_TRANSFORM = promise_error_transform<TVALUE>>
63using generator_channel_future = generator_future<TVALUE, TERROR_TRANSFORM, generator_vtable_type::kNone>;
65template <
class TVALUE>
66class LIBCOPP_COPP_API_HEAD_ONLY generator_context_base {
69 using handle_delegate = promise_caller_manager::handle_delegate;
72 generator_context_base(
const generator_context_base&) =
delete;
73 generator_context_base(generator_context_base&&) =
delete;
74 generator_context_base& operator=(
const generator_context_base&) =
delete;
75 generator_context_base& operator=(generator_context_base&&) =
delete;
78 generator_context_base() =
default;
79 ~generator_context_base() { wake(); }
90# if defined(LIBCOPP_MACRO_ENABLE_CONCEPTS) && LIBCOPP_MACRO_ENABLE_CONCEPTS
91 template <DerivedPromiseBaseType TPROMISE>
93 template <class TPROMISE, typename = std::enable_if_t<std::is_base_of<promise_base_type, TPROMISE>::value>>
97 add_caller(handle_delegate{handle});
101 caller_manager_.remove_caller(handle);
104# if defined(LIBCOPP_MACRO_ENABLE_CONCEPTS) && LIBCOPP_MACRO_ENABLE_CONCEPTS
105 template <DerivedPromiseBaseType TPROMISE>
107 template <class TPROMISE, typename = std::enable_if_t<std::is_base_of<promise_base_type, TPROMISE>::value>>
111 remove_caller(handle_delegate{handle}, inherit_status);
114 LIBCOPP_UTIL_FORCEINLINE bool has_multiple_callers() const noexcept {
return caller_manager_.has_multiple_callers(); }
122 promise_caller_manager caller_manager_;
125template <
class TVALUE,
class TERROR_TRANSFORM>
126class LIBCOPP_COPP_API_HEAD_ONLY generator_context_delegate<TVALUE, TERROR_TRANSFORM, true>
127 :
public generator_context_base<TVALUE> {
129 using base_type = generator_context_base<TVALUE>;
130 using value_type =
typename base_type::value_type;
133 template <
class... TARGS>
134 generator_context_delegate(TARGS&&... args) : base_type(
std::forward<TARGS>(args)...) {}
136 ~generator_context_delegate() { wake(); }
138 using base_type::add_caller;
139 using base_type::is_pending;
140 using base_type::is_ready;
141 using base_type::remove_caller;
142 using base_type::reset_value;
147# if 0 && defined(LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR) && LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR
148 std::exception_ptr unhandled_exception;
151 data_.reset_data(
true);
155# if 0 && defined(LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR) && LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR
157 unhandled_exception = std::current_exception();
159 if (unhandled_exception) {
160 std::rethrow_exception(unhandled_exception);
166 using base_type::data_;
167 using base_type::wake;
170template <
class TVALUE,
class TERROR_TRANSFORM>
171class LIBCOPP_COPP_API_HEAD_ONLY generator_context_delegate<TVALUE, TERROR_TRANSFORM, false>
172 :
public generator_context_base<TVALUE> {
174 using base_type = generator_context_base<TVALUE>;
175 using value_type =
typename base_type::value_type;
178 template <
class... TARGS>
179 generator_context_delegate(TARGS&&... args) : base_type(
std::forward<TARGS>(args)...) {}
181 using base_type::add_caller;
182 using base_type::is_pending;
183 using base_type::is_ready;
184 using base_type::remove_caller;
185 using base_type::reset_value;
187 ~generator_context_delegate() {
189 set_value(TERROR_TRANSFORM()(promise_status::kKilled));
215# if 0 && defined(LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR) && LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR
216 std::exception_ptr unhandled_exception;
219 data_.reset_data(std::forward<U>(in));
223# if 0 && defined(LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR) && LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR
225 unhandled_exception = std::current_exception();
227 if (unhandled_exception) {
228 std::rethrow_exception(unhandled_exception);
234 using base_type::data_;
235 using base_type::wake;
238template <
class TVALUE,
class TERROR_TRANSFORM>
239class LIBCOPP_COPP_API_HEAD_ONLY generator_context
240 :
public generator_context_delegate<TVALUE, TERROR_TRANSFORM,
241 std::is_void<typename std::decay<TVALUE>::type>::value>,
242 public LIBCOPP_COPP_NAMESPACE_ID::memory::default_enable_shared_from_this<
243 generator_context<TVALUE, TERROR_TRANSFORM>> {
246 generator_context_delegate<TVALUE, TERROR_TRANSFORM, std::is_void<typename std::decay<TVALUE>::type>::value>;
247 using value_type =
typename base_type::value_type;
248 using error_transform = TERROR_TRANSFORM;
251 template <
class... TARGS>
252 generator_context(TARGS&&... args) : base_type(
std::forward<TARGS>(args)...) {}
254 using base_type::is_pending;
255 using base_type::is_ready;
256 using base_type::reset_value;
257 using base_type::set_value;
260template <
class TCONTEXT>
261struct LIBCOPP_COPP_API_HEAD_ONLY generator_vtable_type_trait<TCONTEXT, generator_vtable_type::kDefault> {
262 using context_type = TCONTEXT;
263 using context_pointer_type = LIBCOPP_COPP_NAMESPACE_ID::memory::default_strong_rc_ptr<context_type>;
264 using value_type =
typename context_type::value_type;
265 using await_suspend_callback_type = std::function<void(context_pointer_type)>;
266 using await_resume_callback_type = std::function<void(
const context_type&)>;
269template <
class TCONTEXT>
270struct LIBCOPP_COPP_API_HEAD_ONLY generator_vtable_type_trait<TCONTEXT, generator_vtable_type::kLightWeight> {
271 using context_type = TCONTEXT;
272 using context_pointer_type = LIBCOPP_COPP_NAMESPACE_ID::memory::default_strong_rc_ptr<context_type>;
273 using value_type =
typename context_type::value_type;
274 using await_suspend_callback_type = void (*)(context_pointer_type);
275 using await_resume_callback_type = void (*)(
const context_type&);
278template <
class TCONTEXT, generator_vtable_type VTABLE_TYPE>
279class LIBCOPP_COPP_API_HEAD_ONLY generator_vtable {
281 using context_type =
typename generator_vtable_type_trait<TCONTEXT, VTABLE_TYPE>::context_type;
282 using context_pointer_type =
typename generator_vtable_type_trait<TCONTEXT, VTABLE_TYPE>::context_pointer_type;
283 using value_type =
typename generator_vtable_type_trait<TCONTEXT, VTABLE_TYPE>::value_type;
284 using await_suspend_callback_type =
285 typename generator_vtable_type_trait<TCONTEXT, VTABLE_TYPE>::await_suspend_callback_type;
286 using await_resume_callback_type =
287 typename generator_vtable_type_trait<TCONTEXT, VTABLE_TYPE>::await_resume_callback_type;
290 template <
class TSUSPEND,
class TRESUME>
291 generator_vtable(TSUSPEND&& await_suspend_callback, TRESUME&& await_resume_callback)
noexcept(
292 std::is_nothrow_constructible<await_suspend_callback_type, TSUSPEND>::value &&
293 std::is_nothrow_constructible<await_resume_callback_type, TRESUME>::value)
294 : intrusive_ref_counter_(0),
295 await_suspend_callback_(
std::forward<TSUSPEND>(await_suspend_callback)),
296 await_resume_callback_(
std::forward<TRESUME>(await_resume_callback)) {}
298 template <
class TSUSPEND>
299 generator_vtable(TSUSPEND&& await_suspend_callback)
noexcept(
300 std::is_nothrow_constructible<await_suspend_callback_type, TSUSPEND>::value)
301 : intrusive_ref_counter_(0), await_suspend_callback_(
std::forward<TSUSPEND>(await_suspend_callback)) {}
303 generator_vtable(
const generator_vtable&) =
delete;
304 generator_vtable(generator_vtable&&) =
delete;
305 generator_vtable& operator=(
const generator_vtable&) =
delete;
306 generator_vtable& operator=(generator_vtable&&) =
delete;
309 return await_suspend_callback_;
312 return await_suspend_callback_;
315 return await_resume_callback_;
318 return await_resume_callback_;
324 ++p->intrusive_ref_counter_;
332 assert(p->intrusive_ref_counter_ > 0);
333 size_t ref = --p->intrusive_ref_counter_;
340 await_suspend_callback_type await_suspend_callback_;
341 await_resume_callback_type await_resume_callback_;
344template <
class TCONTEXT, generator_vtable_type VTABLE_TYPE>
345class LIBCOPP_COPP_API_HEAD_ONLY generator_vtable_delegate;
348struct is_generator_vtable_delegate;
350template <
class TCONTEXT, generator_vtable_type VTABLE_TYPE>
351struct is_generator_vtable_delegate<generator_vtable_delegate<TCONTEXT, VTABLE_TYPE>> : ::std::true_type {};
354struct is_generator_vtable_delegate : ::std::false_type {};
356template <
class TCONTEXT>
357class LIBCOPP_COPP_API_HEAD_ONLY generator_vtable_delegate<TCONTEXT, generator_vtable_type::kDefault> {
359 using context_type = TCONTEXT;
360 using vtable_type = generator_vtable<context_type, generator_vtable_type::kDefault>;
361 using context_pointer_type = LIBCOPP_COPP_NAMESPACE_ID::memory::default_strong_rc_ptr<context_type>;
362 using value_type =
typename context_type::value_type;
363 using await_suspend_callback_type =
typename vtable_type::await_suspend_callback_type;
364 using await_resume_callback_type =
typename vtable_type::await_resume_callback_type;
366 template <
class TSUSPEND,
class TRESUME>
368 TSUSPEND&& await_suspend_callback,
369 TRESUME&& await_resume_callback)
noexcept(std::is_nothrow_constructible<vtable_type, TSUSPEND, TRESUME>::value)
370 : vtable_(new vtable_type(
std::forward<TSUSPEND>(await_suspend_callback),
371 std::forward<TRESUME>(await_resume_callback))) {}
373 template <class TSUSPEND, class = std::enable_if_t<!is_generator_vtable_delegate<TSUSPEND>::value>>
375 std::is_nothrow_constructible<vtable_type, TSUSPEND>::value)
376 : vtable_(new vtable_type(
std::forward<TSUSPEND>(await_suspend_callback))) {}
381 : vtable_(std::move(other.vtable_)) {}
383 : vtable_(other.vtable_) {}
386 if (vtable_ && vtable_->get_await_suspend_callback()) {
387 vtable_->get_await_suspend_callback()(context.shared_from_this());
392 if (vtable_ && vtable_->get_await_resume_callback()) {
393 vtable_->get_await_resume_callback()(context);
398 copp::memory::intrusive_ptr<vtable_type> vtable_;
401template <
class TCONTEXT>
402class LIBCOPP_COPP_API_HEAD_ONLY generator_vtable_delegate<TCONTEXT, generator_vtable_type::kLightWeight> {
404 using context_type = TCONTEXT;
405 using vtable_type = generator_vtable<context_type, generator_vtable_type::kLightWeight>;
406 using context_pointer_type = LIBCOPP_COPP_NAMESPACE_ID::memory::default_strong_rc_ptr<context_type>;
407 using value_type =
typename context_type::value_type;
408 using await_suspend_callback_type =
typename vtable_type::await_suspend_callback_type;
409 using await_resume_callback_type =
typename vtable_type::await_resume_callback_type;
411 template <
class TSUSPEND,
class TRESUME>
413 TRESUME&& await_resume_callback) noexcept
414 : vtable_(
new vtable_type(std::forward<TSUSPEND>(await_suspend_callback),
415 std::forward<TRESUME>(await_resume_callback))) {}
417 template <
class TSUSPEND>
419 : vtable_(
new vtable_type(std::forward<TSUSPEND>(await_suspend_callback),
nullptr)) {}
424 : vtable_(other.vtable_) {}
427 if (vtable_ && vtable_->get_await_suspend_callback()) {
428 vtable_->get_await_suspend_callback()(context.shared_from_this());
433 if (vtable_ && vtable_->get_await_resume_callback()) {
434 vtable_->get_await_resume_callback()(context);
439 copp::memory::intrusive_ptr<vtable_type> vtable_;
442template <
class TCONTEXT>
443class LIBCOPP_COPP_API_HEAD_ONLY generator_vtable_delegate<TCONTEXT, generator_vtable_type::kNone> {
445 using context_type = TCONTEXT;
446 using context_pointer_type = LIBCOPP_COPP_NAMESPACE_ID::memory::default_strong_rc_ptr<context_type>;
447 using value_type =
typename context_type::value_type;
457template <
class TCONTEXT, generator_vtable_type VTABLE_TYPE>
458class LIBCOPP_COPP_API_HEAD_ONLY generator_awaitable_base :
public awaitable_base_type {
460 using context_type = TCONTEXT;
461 using context_pointer_type = LIBCOPP_COPP_NAMESPACE_ID::memory::default_strong_rc_ptr<context_type>;
462 using value_type =
typename context_type::value_type;
463 using vtable_delegate_type = generator_vtable_delegate<context_type, VTABLE_TYPE>;
466 generator_awaitable_base(context_type* context,
const vtable_delegate_type& vtable_delegate)
467 : context_{context}, vtable_delegate_(vtable_delegate) {}
469 inline bool await_ready() noexcept {
470 if (
nullptr == context_) {
474 return context_->is_ready();
477# if defined(LIBCOPP_MACRO_ENABLE_CONCEPTS) && LIBCOPP_MACRO_ENABLE_CONCEPTS
478 template <DerivedPromiseBaseType TCPROMISE>
480 template <class TCPROMISE, typename = std::enable_if_t<std::is_base_of<promise_base_type, TCPROMISE>::value>>
483 if (
nullptr != context_ && caller.promise().get_status() < promise_status::kDone) {
485 context_->add_caller(caller);
488 caller.promise().set_flag(promise_flag::kInternalWaitting,
true);
491 vtable_delegate_.trigger_suspend_callback(*context_);
502 promise_status detach() noexcept {
503 promise_status result_status;
505 result_status = promise_status::kInvalid;
506 }
else if (context_->is_ready()) {
507 result_status = promise_status::kDone;
509 result_status = promise_status::kKilled;
513 auto caller = get_caller();
516 if (
nullptr != caller.promise) {
517 caller.promise->set_flag(promise_flag::kInternalWaitting,
false);
519 if (
nullptr != context_) {
520 if (!context_->is_ready() &&
nullptr != caller.promise) {
521 result_status = caller.promise->get_status();
524 context_->remove_caller(caller);
528 vtable_delegate_.trigger_resume_callback(*context_);
534 return result_status;
543 inline context_type* get_context() noexcept {
return context_; }
546 context_type* context_;
547 vtable_delegate_type vtable_delegate_;
550template <
class TCONTEXT, generator_vtable_type VTABLE_TYPE>
551class LIBCOPP_COPP_API_HEAD_ONLY generator_awaitable<TCONTEXT, true, VTABLE_TYPE>
552 :
public generator_awaitable_base<TCONTEXT, VTABLE_TYPE> {
554 using base_type = generator_awaitable_base<TCONTEXT, VTABLE_TYPE>;
555 using value_type =
typename base_type::value_type;
556 using context_type =
typename base_type::context_type;
557 using context_pointer_type =
typename base_type::context_pointer_type;
558 using vtable_delegate_type =
typename base_type::vtable_delegate_type;
559 using error_transform =
typename context_type::error_transform;
562 using base_type::await_ready;
563 using base_type::await_suspend;
564 using base_type::get_caller;
565 using base_type::set_caller;
566 generator_awaitable(context_type* context,
const vtable_delegate_type& vtable_delegate)
567 : base_type(context, vtable_delegate) {}
569 inline void await_resume() { detach(); }
572 using base_type::detach;
573 using base_type::get_context;
576template <
class TCONTEXT, generator_vtable_type VTABLE_TYPE>
577class LIBCOPP_COPP_API_HEAD_ONLY generator_awaitable<TCONTEXT, false, VTABLE_TYPE>
578 :
public generator_awaitable_base<TCONTEXT, VTABLE_TYPE> {
580 using base_type = generator_awaitable_base<TCONTEXT, VTABLE_TYPE>;
581 using value_type =
typename base_type::value_type;
582 using context_type =
typename base_type::context_type;
583 using context_pointer_type =
typename base_type::context_pointer_type;
584 using vtable_delegate_type =
typename base_type::vtable_delegate_type;
585 using error_transform =
typename context_type::error_transform;
588 using base_type::await_ready;
589 using base_type::await_suspend;
590 using base_type::get_caller;
591 using base_type::set_caller;
592 generator_awaitable(context_type* context,
const vtable_delegate_type& vtable_delegate)
593 : base_type(context, vtable_delegate) {}
596 bool has_multiple_callers;
598 has_multiple_callers = get_context()->has_multiple_callers();
600 has_multiple_callers =
false;
602 promise_status result_status = detach();
604 if (promise_status::kDone != result_status) {
605 return error_transform()(result_status);
609 if (has_multiple_callers) {
610 return *get_context()->data();
612 return multiple_callers_constructor<value_type>::return_value(*get_context()->
data());
615 return error_transform()(promise_status::kInvalid);
620 using base_type::detach;
621 using base_type::get_context;
625struct is_generator_future;
627template <
class TVALUE,
class TERROR_TRANSFORM, generator_vtable_type VTABLE_TYPE>
628struct is_generator_future<generator_future<TVALUE, TERROR_TRANSFORM, VTABLE_TYPE>> : ::std::true_type {};
631struct is_generator_future : ::std::false_type {};
633template <
class TVALUE,
class TERROR_TRANSFORM, generator_vtable_type VTABLE_TYPE>
634class LIBCOPP_COPP_API_HEAD_ONLY generator_future {
637 using error_transform = TERROR_TRANSFORM;
638 using self_type = generator_future<value_type, error_transform, VTABLE_TYPE>;
639 using context_type = generator_context<value_type, error_transform>;
640 using context_pointer_type = LIBCOPP_COPP_NAMESPACE_ID::memory::default_strong_rc_ptr<context_type>;
641 using awaitable_type =
642 generator_awaitable<context_type, std::is_void<typename std::decay<value_type>::type>::value, VTABLE_TYPE>;
643 using vtable_delegate_type = generator_vtable_delegate<context_type, VTABLE_TYPE>;
646 template <
class TSUSPEND,
class TRESUME,
647 class = nostd::enable_if_t<!is_generator_vtable_delegate<nostd::decay_t<TSUSPEND>>::value>>
648 inline generator_future(TSUSPEND&& await_suspend_callback,
649 TRESUME&& await_resume_callback)
noexcept(std::is_nothrow_constructible<context_type>::value)
651 vtable_delegate_(
std::forward<TSUSPEND>(await_suspend_callback),
std::forward<TRESUME>(await_resume_callback)) {
654 template <
class TSUSPEND,
class = nostd::enable_if_t<!is_generator_vtable_delegate<nostd::decay_t<TSUSPEND>>::value &&
655 !is_generator_future<nostd::decay_t<TSUSPEND>>::value>>
656 inline generator_future(TSUSPEND&& await_suspend_callback)
noexcept(
657 std::is_nothrow_constructible<context_type>::value)
659 vtable_delegate_(
std::forward<TSUSPEND>(await_suspend_callback)) {}
661 inline generator_future() noexcept(
std::is_nothrow_constructible<context_type>::value)
662 : context_(LIBCOPP_COPP_NAMESPACE_ID::
memory::default_make_strong<context_type>()) {}
664 inline generator_future(generator_future&&) =
default;
665 inline generator_future(
const generator_future&) =
default;
666 inline generator_future& operator=(generator_future&&) =
default;
667 inline generator_future& operator=(
const generator_future&) =
default;
669 ~generator_future() {
675 inline awaitable_type
operator co_await() {
677 return awaitable_type{context_.get(), vtable_delegate_};
680 inline bool is_ready() const noexcept {
685 return context_->is_ready();
688 inline bool is_pending() const noexcept {
693 return context_->is_pending();
696 inline promise_status get_status() const noexcept {
698 return promise_status::kInvalid;
701 if (context_->is_ready()) {
702 return promise_status::kDone;
705 return promise_status::kRunning;
713 template <
class TFUTURE>
714 friend class LIBCOPP_COPP_API_HEAD_ONLY some_delegate;
716 template <
class TFUTURE,
class, generator_vtable_type>
717 friend struct LIBCOPP_COPP_API_HEAD_ONLY some_delegate_generator_action;
719 context_pointer_type context_;
720 vtable_delegate_type vtable_delegate_;
724template <
class TVALUE,
class TERROR_TRANSFORM, generator_vtable_type VTABLE_TYPE>
725struct LIBCOPP_COPP_API_HEAD_ONLY some_delegate_generator_action {
726 using future_type = generator_future<TVALUE, TERROR_TRANSFORM, VTABLE_TYPE>;
727 using context_type = some_delegate_context<future_type>;
729 inline static void suspend_future(
const promise_caller_manager::handle_delegate& caller, future_type& generator) {
730 generator.get_context()->add_caller(caller);
733 generator.vtable_delegate_.trigger_suspend_callback(*generator.get_context());
736 inline static void resume_future(
const promise_caller_manager::handle_delegate& caller, future_type& generator) {
737 generator.get_context()->remove_caller(caller);
740 generator.vtable_delegate_.trigger_resume_callback(*generator.get_context());
743 inline static bool is_pending(future_type& future_object)
noexcept {
return future_object.is_pending(); }
746template <
class TVALUE,
class TERROR_TRANSFORM, generator_vtable_type VTABLE_TYPE>
747class LIBCOPP_COPP_API_HEAD_ONLY some_delegate<generator_future<TVALUE, TERROR_TRANSFORM, VTABLE_TYPE>>
748 :
public some_delegate_base<generator_future<TVALUE, TERROR_TRANSFORM, VTABLE_TYPE>,
749 some_delegate_generator_action<TVALUE, TERROR_TRANSFORM, VTABLE_TYPE>> {
751 using base_type = some_delegate_base<generator_future<TVALUE, TERROR_TRANSFORM, VTABLE_TYPE>,
752 some_delegate_generator_action<TVALUE, TERROR_TRANSFORM, VTABLE_TYPE>>;
753 using future_type =
typename base_type::future_type;
754 using value_type =
typename base_type::value_type;
755 using ready_output_type =
typename base_type::ready_output_type;
756 using context_type =
typename base_type::context_type;
758 using base_type::run;
761template <
class TVALUE,
class TERROR_TRANSFORM = promise_error_transform<TVALUE>>
762using generator_channel_receiver = generator_channel_future<TVALUE, TERROR_TRANSFORM>;
764template <
class TVALUE,
class TERROR_TRANSFORM = promise_error_transform<TVALUE>>
765using generator_channel_sender =
typename generator_channel_receiver<TVALUE, TERROR_TRANSFORM>::context_pointer_type;
767template <
class TVALUE,
class TERROR_TRANSFORM = promise_error_transform<TVALUE>>
768inline std::pair<generator_channel_receiver<TVALUE, TERROR_TRANSFORM>,
769 generator_channel_sender<TVALUE, TERROR_TRANSFORM>>
771 generator_channel_receiver<TVALUE, TERROR_TRANSFORM>
future;
772 generator_channel_sender<TVALUE, TERROR_TRANSFORM> context =
future.get_context();
773 return std::make_pair(std::move(
future), std::move(context));
776LIBCOPP_COPP_NAMESPACE_END
#define LIBCOPP_UTIL_FORCEINLINE
#define LIBCOPP_UTIL_LIKELY_CONDITION(__C)
#define LIBCOPP_UTIL_UNLIKELY_CONDITION(__C)
#define LIBCOPP_MACRO_STD_COROUTINE_NAMESPACE
#define LIBCOPP_UTIL_INTRUSIVE_PTR_ATOMIC_TYPE
constexpr auto data(TCONTAINER &&container) -> decltype(container.data())
LIBCOPP_UTIL_FORCEINLINE default_strong_rc_ptr< T > default_make_strong(ArgsT &&... args)
void intrusive_ptr_release(X *p)
void intrusive_ptr_add_ref(X *p)
std::shared_ptr< cli::cmd_option_value > value_type