9#include <libcopp/utils/config/libcopp_build_features.h>
23#if defined(LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR) && LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR
30#if defined(LIBCOPP_MACRO_ENABLE_STD_COROUTINE) && LIBCOPP_MACRO_ENABLE_STD_COROUTINE
32LIBCOPP_COTASK_NAMESPACE_BEGIN
34template <
class TVALUE>
35class LIBCOPP_COTASK_API_HEAD_ONLY task_context_base;
37template <
class TVALUE,
class TERROR_TRANSFORM,
bool RETURN_VOID>
38class LIBCOPP_COTASK_API_HEAD_ONLY task_context_delegate;
40template <
class TVALUE,
class TPRIVATE_DATA,
class TERROR_TRANSFORM>
41class LIBCOPP_COTASK_API_HEAD_ONLY task_context;
43template <
class TVALUE,
class TPRIVATE_DATA,
class TERROR_TRANSFORM>
44class LIBCOPP_COTASK_API_HEAD_ONLY task_future_base;
46template <
class TVALUE,
class TPRIVATE_DATA,
class TERROR_TRANSFORM>
47class LIBCOPP_COTASK_API_HEAD_ONLY task_future;
49template <
class TVALUE,
class TPRIVATE_DATA,
class TERROR_TRANSFORM,
bool RETURN_VOID>
50class LIBCOPP_COTASK_API_HEAD_ONLY task_promise_base;
52template <
class TCONTEXT>
53class LIBCOPP_COTASK_API_HEAD_ONLY task_awaitable_base;
55template <
class TCONTEXT,
bool RETURN_VOID>
56class LIBCOPP_COTASK_API_HEAD_ONLY task_awaitable;
58template <
class TVALUE>
59class LIBCOPP_COTASK_API_HEAD_ONLY task_context_base {
62 using id_type = LIBCOPP_COPP_NAMESPACE_ID::util::uint64_id_allocator::value_type;
63 using id_allocator_type = LIBCOPP_COPP_NAMESPACE_ID::util::uint64_id_allocator;
64 using handle_delegate = LIBCOPP_COPP_NAMESPACE_ID::promise_caller_manager::handle_delegate;
65 using task_status_type = LIBCOPP_COPP_NAMESPACE_ID::promise_status;
66 using promise_flag = LIBCOPP_COPP_NAMESPACE_ID::promise_flag;
69 task_context_base(
const task_context_base&) =
delete;
70 task_context_base(task_context_base&&) =
delete;
71 task_context_base& operator=(
const task_context_base&) =
delete;
72 task_context_base& operator=(task_context_base&&) =
delete;
75 task_context_base() noexcept
76 : current_handle_(
nullptr)
77# if defined(LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER) && LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER
79 binding_manager_ptr_(
nullptr),
80 binding_manager_fn_(
nullptr)
83 id_allocator_type id_allocator;
84 id_ = id_allocator.allocate();
87 ~task_context_base() noexcept {
93 if (
nullptr != current_handle_.promise && current_handle_.promise->check_flag(promise_flag::kHasReturned)) {
97 return data_.is_ready();
102 inline task_status_type get_status() const noexcept {
103 if (current_handle_.promise) {
104 return current_handle_.promise->get_status();
107 return task_status_type::kInvalid;
113 if (
nullptr != current_handle_.promise) {
114 return current_handle_.promise->has_multiple_callers();
122 if (
nullptr != current_handle_.promise) {
123 current_handle_.promise->add_caller(handle);
127# if defined(LIBCOPP_MACRO_ENABLE_CONCEPTS) && LIBCOPP_MACRO_ENABLE_CONCEPTS
128 template <LIBCOPP_COPP_NAMESPACE_ID::DerivedPromiseBaseType TPROMISE>
130 template <
class TPROMISE,
131 typename = std::enable_if_t<std::is_base_of<LIBCOPP_COPP_NAMESPACE_ID::promise_base_type, TPROMISE>::value>>
135 add_caller(handle_delegate{handle});
139 if (
nullptr != current_handle_.promise) {
140 current_handle_.promise->remove_caller(handle,
false);
144# if defined(LIBCOPP_MACRO_ENABLE_CONCEPTS) && LIBCOPP_MACRO_ENABLE_CONCEPTS
145 template <LIBCOPP_COPP_NAMESPACE_ID::DerivedPromiseBaseType TPROMISE>
147 template <
class TPROMISE,
148 typename = std::enable_if_t<std::is_base_of<LIBCOPP_COPP_NAMESPACE_ID::promise_base_type, TPROMISE>::value>>
152 remove_caller(handle_delegate{handle}, inherit_status);
155# if defined(LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER) && LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER
157 void* manager_ptr = binding_manager_ptr_;
158 void (*manager_fn)(
void*, task_context_base<value_type>&) = binding_manager_fn_;
159 binding_manager_ptr_ =
nullptr;
160 binding_manager_fn_ =
nullptr;
163 if (
nullptr != manager_ptr &&
nullptr != manager_fn) {
164 (*manager_fn)(manager_ptr, *
this);
170 template <
class,
class,
class,
bool>
171 friend class LIBCOPP_COTASK_API_HEAD_ONLY task_promise_base;
173 template <
class,
class,
class>
174 friend class LIBCOPP_COTASK_API_HEAD_ONLY task_future_base;
176 template <
class,
class,
class>
177 friend class LIBCOPP_COTASK_API_HEAD_ONLY task_future;
179 template <
class TCONTEXT>
180 friend class LIBCOPP_COTASK_API_HEAD_ONLY task_awaitable_base;
182 inline void force_finish() noexcept {
184 if (current_handle_.promise->get_status() < task_status_type::kDone) {
185 current_handle_.promise->set_status(task_status_type::kKilled);
190 while (current_handle_.handle && !current_handle_.handle.done() && current_handle_.promise &&
191 !current_handle_.promise->check_flag(promise_flag::kHasReturned)) {
192 current_handle_.handle.resume();
196 inline void force_destroy() noexcept {
198 handle_delegate current_handle = current_handle_;
199 current_handle_ =
nullptr;
201 if (
nullptr != current_handle.promise) {
202 current_handle.promise->set_flag(promise_flag::kDestroying,
true);
204 if (current_handle.handle) {
205 current_handle.handle.destroy();
215 LIBCOPP_COPP_NAMESPACE_ID::future::future<TVALUE> data_;
217# if defined(LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER) && LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER
219 class LIBCOPP_COTASK_API_HEAD_ONLY task_manager_helper {
223 static bool setup_task_manager(task_context_base<value_type>& context,
void* manager_ptr,
224 void (*fn)(
void*, task_context_base<value_type>&)) {
225 if (context.binding_manager_ptr_ !=
nullptr) {
229 context.binding_manager_ptr_ = manager_ptr;
230 context.binding_manager_fn_ = fn;
234 static bool cleanup_task_manager(task_context_base<value_type>& context,
void* manager_ptr) {
235 if (context.binding_manager_ptr_ != manager_ptr) {
239 context.binding_manager_ptr_ =
nullptr;
240 context.binding_manager_fn_ =
nullptr;
248 LIBCOPP_COPP_NAMESPACE_ID::util::lock::atomic_int_type<
249# if LIBCOPP_MACRO_ENABLE_MULTI_THREAD
252 LIBCOPP_COPP_NAMESPACE_ID::util::lock::unsafe_int_type<size_t>
256 LIBCOPP_COPP_NAMESPACE_ID::util::lock::spin_lock internal_operation_lock_;
257 handle_delegate current_handle_;
258# if defined(LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER) && LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER
259 void* binding_manager_ptr_;
260 void (*binding_manager_fn_)(
void*, task_context_base<value_type>&);
264template <
class TVALUE,
class TERROR_TRANSFORM>
265class LIBCOPP_COTASK_API_HEAD_ONLY task_context_delegate<TVALUE, TERROR_TRANSFORM, true>
266 :
public task_context_base<TVALUE> {
268 using base_type = task_context_base<TVALUE>;
269 using id_type =
typename base_type::id_type;
270 using value_type =
typename base_type::value_type;
271 using handle_delegate =
typename base_type::handle_delegate;
272 using task_status_type =
typename base_type::task_status_type;
273 using promise_flag =
typename base_type::promise_flag;
274 using error_transform = TERROR_TRANSFORM;
277 ~task_context_delegate() {}
279 using base_type::is_pending;
280 using base_type::is_ready;
285 template <
class TCONTEXT>
286 friend class LIBCOPP_COTASK_API_HEAD_ONLY task_awaitable_base;
288 template <
class,
class,
class>
289 friend class LIBCOPP_COTASK_API_HEAD_ONLY task_future;
291 template <
class,
class,
class>
292 friend struct LIBCOPP_COTASK_API_HEAD_ONLY some_delegate_task_action;
294 using base_type::add_caller;
295 using base_type::data_;
296 using base_type::remove_caller;
297# if defined(LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER) && LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER
298 using base_type::unbind_from_manager;
302template <
class TVALUE,
class TERROR_TRANSFORM>
303class LIBCOPP_COTASK_API_HEAD_ONLY task_context_delegate<TVALUE, TERROR_TRANSFORM, false>
304 :
public task_context_base<TVALUE> {
306 using base_type = task_context_base<TVALUE>;
307 using id_type =
typename base_type::id_type;
308 using value_type =
typename base_type::value_type;
309 using handle_delegate =
typename base_type::handle_delegate;
310 using task_status_type =
typename base_type::task_status_type;
311 using promise_flag =
typename base_type::promise_flag;
312 using error_transform = TERROR_TRANSFORM;
315 using base_type::is_pending;
316 using base_type::is_ready;
318 ~task_context_delegate() {
320 set_value(error_transform()(task_status_type::kKilled));
342 data_.reset_data(std::forward<U>(in));
346 template <
class TCONTEXT>
347 friend class LIBCOPP_COTASK_API_HEAD_ONLY task_awaitable_base;
349 template <
class,
class,
class>
350 friend class LIBCOPP_COTASK_API_HEAD_ONLY task_future;
352 template <
class,
class,
class>
353 friend struct LIBCOPP_COTASK_API_HEAD_ONLY some_delegate_task_action;
355 using base_type::add_caller;
356 using base_type::data_;
357 using base_type::remove_caller;
358# if defined(LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER) && LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER
359 using base_type::unbind_from_manager;
363template <
class TPRIVATE_DATA>
364class LIBCOPP_COTASK_API_HEAD_ONLY task_private_data {
366 inline task_private_data() noexcept : data_(
nullptr) {}
367 inline task_private_data(TPRIVATE_DATA* input) noexcept : data_(input) {}
368 inline task_private_data(task_private_data&& other)
noexcept =
default;
369 inline task_private_data& operator=(task_private_data&&) noexcept = default;
370 inline task_private_data(const task_private_data&) = delete;
371 inline task_private_data& operator=(const task_private_data&) = delete;
372 inline ~task_private_data() {}
374 inline bool await_ready() const noexcept {
return true; }
375 inline TPRIVATE_DATA* await_resume() const noexcept {
return data_; }
376 inline void await_suspend(LIBCOPP_COPP_NAMESPACE_ID::promise_base_type::type_erased_handle_type)
noexcept {}
379 template <
class,
class,
class>
380 friend class LIBCOPP_COTASK_API_HEAD_ONLY task_context;
382 template <
class,
class,
class>
383 friend class LIBCOPP_COTASK_API_HEAD_ONLY task_future;
385 TPRIVATE_DATA* data_;
389class LIBCOPP_COTASK_API_HEAD_ONLY task_pick_id {
391 inline task_pick_id() noexcept : data_(0) {}
392 inline task_pick_id(TID input) noexcept : data_(input) {}
393 inline task_pick_id(task_pick_id&& other)
noexcept =
default;
394 inline task_pick_id& operator=(task_pick_id&&) noexcept = default;
395 inline task_pick_id(const task_pick_id&) = delete;
396 inline task_pick_id& operator=(const task_pick_id&) = delete;
397 inline ~task_pick_id() {}
399 inline bool await_ready() const noexcept {
return true; }
400 inline TID await_resume() const noexcept {
return data_; }
401 inline void await_suspend(LIBCOPP_COPP_NAMESPACE_ID::promise_base_type::type_erased_handle_type)
noexcept {}
404 template <
class,
class,
class>
405 friend class LIBCOPP_COTASK_API_HEAD_ONLY task_context;
407 template <
class,
class,
class>
408 friend class LIBCOPP_COTASK_API_HEAD_ONLY task_future;
413template <
class TVALUE,
class TERROR_TRANSFORM>
414class LIBCOPP_COTASK_API_HEAD_ONLY task_context<TVALUE, void, TERROR_TRANSFORM>
415 :
public task_context_delegate<TVALUE, TERROR_TRANSFORM, std::is_void<typename std::decay<TVALUE>::type>::value> {
418 task_context_delegate<TVALUE, TERROR_TRANSFORM, std::is_void<typename std::decay<TVALUE>::type>::value>;
419 using value_type =
typename base_type::value_type;
420 using id_type =
typename base_type::id_type;
421 using private_data_type = void;
422 using handle_delegate =
typename base_type::handle_delegate;
423 using task_status_type =
typename base_type::task_status_type;
424 using promise_flag =
typename base_type::promise_flag;
425 using error_transform =
typename base_type::error_transform;
428 using base_type::is_pending;
429 using base_type::is_ready;
430 using base_type::set_value;
432 template <
class... TARGS>
433 task_context(TARGS&&...) {}
436template <
class TVALUE,
class TPRIVATE_DATA,
class TERROR_TRANSFORM>
437class LIBCOPP_COTASK_API_HEAD_ONLY task_context
438 :
public task_context_delegate<TVALUE, TERROR_TRANSFORM, std::is_void<typename std::decay<TVALUE>::type>::value> {
441 task_context_delegate<TVALUE, TERROR_TRANSFORM, std::is_void<typename std::decay<TVALUE>::type>::value>;
442 using value_type =
typename base_type::value_type;
443 using private_data_type = TPRIVATE_DATA;
444 using handle_delegate =
typename base_type::handle_delegate;
445 using task_status_type =
typename base_type::task_status_type;
446 using promise_flag =
typename base_type::promise_flag;
447 using error_transform =
typename base_type::error_transform;
450 using base_type::is_pending;
451 using base_type::is_ready;
452 using base_type::set_value;
454 template <
class... TARGS>
455 task_context(TARGS&&... args)
457 LIBCOPP_COPP_NAMESPACE_ID::callable_promise_value_constructor<
459 !
std::is_constructible<private_data_type, TARGS...>::value>::construct(
std::forward<TARGS>(args)...)) {}
461 private_data_type& get_private_data() noexcept {
return private_data_; }
462 const private_data_type& get_private_data() const noexcept {
return private_data_; }
465 private_data_type private_data_;
468template <
class TVALUE,
class TPRIVATE_DATA,
class TERROR_TRANSFORM>
469class LIBCOPP_COTASK_API_HEAD_ONLY task_promise_base<TVALUE, TPRIVATE_DATA, TERROR_TRANSFORM, true>
470 :
public LIBCOPP_COPP_NAMESPACE_ID::promise_base_type {
473 using context_type = task_context<value_type, TPRIVATE_DATA, TERROR_TRANSFORM>;
474 using private_data_type =
typename context_type::private_data_type;
475 using context_pointer_type = LIBCOPP_COPP_NAMESPACE_ID::memory::default_strong_rc_ptr<context_type>;
476 using handle_delegate =
typename context_type::handle_delegate;
477 using task_status_type = LIBCOPP_COPP_NAMESPACE_ID::promise_status;
479 template <
class... TARGS>
480 task_promise_base(TARGS&&... args)
481 : context_strong_ref_(
484 void return_void() noexcept {
485 set_flag(LIBCOPP_COPP_NAMESPACE_ID::promise_flag::kHasReturned,
true);
487 if (get_status() < task_status_type::kDone) {
488 set_status(task_status_type::kDone);
492 get_context()->set_value();
498 context_pointer_type ret = std::move(context_strong_ref_);
499 context_strong_ref_.reset();
505 template <
class TPROMISE,
typename = std::enable_if_t<std::is_base_of<
506 task_promise_base<TVALUE, TPRIVATE_DATA, TERROR_TRANSFORM, true>, TPROMISE>::value>>
510 get_context()->initialize_handle(handle_delegate{origin_handle});
515 context_pointer_type context_strong_ref_;
518template <
class TVALUE,
class TPRIVATE_DATA,
class TERROR_TRANSFORM>
519class LIBCOPP_COTASK_API_HEAD_ONLY task_promise_base<TVALUE, TPRIVATE_DATA, TERROR_TRANSFORM, false>
520 :
public LIBCOPP_COPP_NAMESPACE_ID::promise_base_type {
523 using context_type = task_context<value_type, TPRIVATE_DATA, TERROR_TRANSFORM>;
524 using private_data_type =
typename context_type::private_data_type;
525 using context_pointer_type = LIBCOPP_COPP_NAMESPACE_ID::memory::default_strong_rc_ptr<context_type>;
526 using task_status_type = LIBCOPP_COPP_NAMESPACE_ID::promise_status;
528 template <
class... TARGS>
529 task_promise_base(TARGS&&... args)
530 : context_strong_ref_(
533 void return_value(value_type value) {
534 set_flag(LIBCOPP_COPP_NAMESPACE_ID::promise_flag::kHasReturned,
true);
536 if (get_status() < task_status_type::kDone) {
537 set_status(task_status_type::kDone);
540 get_context()->set_value(std::move(value));
546 return get_context()->data();
553 return get_context()->data();
560 context_pointer_type ret = std::move(context_strong_ref_);
561 context_strong_ref_.reset();
567 template <
class TPROMISE,
typename = std::enable_if_t<std::is_base_of<
568 task_promise_base<TVALUE, TPRIVATE_DATA, TERROR_TRANSFORM, false>, TPROMISE>::value>>
572 get_context()->initialize_handle(handle_delegate{origin_handle});
577 context_pointer_type context_strong_ref_;
580template <
class TCONTEXT>
581class LIBCOPP_COTASK_API_HEAD_ONLY task_awaitable_base :
public LIBCOPP_COPP_NAMESPACE_ID::awaitable_base_type {
583 using context_type = TCONTEXT;
584 using context_pointer_type = LIBCOPP_COPP_NAMESPACE_ID::memory::default_strong_rc_ptr<context_type>;
585 using value_type =
typename context_type::value_type;
586 using task_status_type = LIBCOPP_COPP_NAMESPACE_ID::promise_status;
587 using promise_flag = LIBCOPP_COPP_NAMESPACE_ID::promise_flag;
590 task_awaitable_base(context_type* context) : context_{context} {}
592 inline bool await_ready() noexcept {
597 if (context_->is_ready()) {
601 if (
nullptr == context_->get_handle_delegate().promise) {
605 if (context_->get_handle_delegate().promise->get_status() >= task_status_type::kDone) {
612# if defined(LIBCOPP_MACRO_ENABLE_CONCEPTS) && LIBCOPP_MACRO_ENABLE_CONCEPTS
613 template <LIBCOPP_COPP_NAMESPACE_ID::DerivedPromiseBaseType TCPROMISE>
615 template <
class TCPROMISE,
typename = std::enable_if_t<
616 std::is_base_of<LIBCOPP_COPP_NAMESPACE_ID::promise_base_type, TCPROMISE>::value>>
619 if (
nullptr != context_ && caller.promise().get_status() < task_status_type::kDone) {
621 context_->add_caller(caller);
624 caller.promise().set_flag(promise_flag::kInternalWaitting,
true);
634 task_status_type detach() noexcept {
635 task_status_type result_status;
637 result_status = task_status_type::kInvalid;
638 }
else if (context_->is_ready()) {
639 result_status = task_status_type::kDone;
641 result_status = task_status_type::kKilled;
645 auto caller = get_caller();
648 if (
nullptr != caller.promise) {
649 caller.promise->set_flag(promise_flag::kInternalWaitting,
false);
652 if (!context_->is_ready() &&
nullptr != caller.promise) {
653 result_status = caller.promise->get_status();
656 context_->remove_caller(caller);
663 return result_status;
675 context_type* context_;
678template <
class TCONTEXT>
679class LIBCOPP_COTASK_API_HEAD_ONLY task_awaitable<TCONTEXT, true> :
public task_awaitable_base<TCONTEXT> {
681 using base_type = task_awaitable_base<TCONTEXT>;
682 using value_type =
typename base_type::value_type;
683 using context_type =
typename base_type::context_type;
684 using context_pointer_type =
typename base_type::context_pointer_type;
685 using task_status_type =
typename base_type::task_status_type;
686 using promise_flag =
typename base_type::promise_flag;
687 using error_transform =
typename context_type::error_transform;
690 using base_type::await_ready;
691 using base_type::await_suspend;
692 using base_type::get_caller;
693 using base_type::set_caller;
694 task_awaitable(context_type* context) : base_type(context) {}
696 inline void await_resume() { detach(); }
699 using base_type::detach;
700 using base_type::get_context;
703template <
class TCONTEXT>
704class LIBCOPP_COTASK_API_HEAD_ONLY task_awaitable<TCONTEXT, false> :
public task_awaitable_base<TCONTEXT> {
706 using base_type = task_awaitable_base<TCONTEXT>;
707 using value_type =
typename base_type::value_type;
708 using context_type =
typename base_type::context_type;
709 using context_pointer_type =
typename base_type::context_pointer_type;
710 using task_status_type =
typename base_type::task_status_type;
711 using promise_flag =
typename base_type::promise_flag;
712 using error_transform =
typename context_type::error_transform;
715 using base_type::await_ready;
716 using base_type::await_suspend;
717 using base_type::get_caller;
718 using base_type::set_caller;
719 task_awaitable(context_type* context) : base_type(context) {}
722 bool has_multiple_callers;
724 has_multiple_callers = get_context()->has_multiple_callers();
726 has_multiple_callers =
false;
728 task_status_type result_status = detach();
730 if (task_status_type::kDone != result_status) {
731 return error_transform()(result_status);
735 if (has_multiple_callers) {
736 return *get_context()->data();
738 return LIBCOPP_COPP_NAMESPACE_ID::multiple_callers_constructor<value_type>::return_value(
739 *get_context()->
data());
742 return error_transform()(task_status_type::kInvalid);
747 using base_type::detach;
748 using base_type::get_context;
751template <
class TVALUE,
class TPRIVATE_DATA,
class TERROR_TRANSFORM>
752class LIBCOPP_COTASK_API_HEAD_ONLY task_future_base {
755 using context_type = task_context<value_type, TPRIVATE_DATA, TERROR_TRANSFORM>;
756 using id_type =
typename context_type::id_type;
757 using private_data_type =
typename context_type::private_data_type;
758 using context_pointer_type = LIBCOPP_COPP_NAMESPACE_ID::memory::default_strong_rc_ptr<context_type>;
759 using task_status_type =
typename context_type::task_status_type;
760 using promise_flag =
typename context_type::promise_flag;
763 task_future_base() noexcept = default;
765 task_future_base(context_pointer_type context) noexcept : context_{context} {
767 ++context_->future_counter_;
771 task_future_base(
const task_future_base& other) noexcept : context_{other.context_} {
773 ++context_->future_counter_;
777 task_future_base(task_future_base&& other) noexcept : context_{std::move(other.context_)} { other.context_.reset(); }
779 task_future_base& operator=(
const task_future_base& other)
noexcept {
784 task_future_base& operator=(task_future_base&& other)
noexcept {
789 ~task_future_base() {
794 inline friend bool operator==(
const task_future_base& l,
const task_future_base& r)
noexcept {
795 return l.context_ == r.context_;
798 inline friend bool operator!=(
const task_future_base& l,
const task_future_base& r)
noexcept {
799 return l.context_ != r.context_;
802 inline operator bool() const noexcept {
return valid(); }
804 void assign(
const task_future_base& other)
noexcept {
805 if (
this == &other || context_ == other.context_) {
812 ++other.context_->future_counter_;
814 context_ = other.context_;
817 void assign(task_future_base&& other)
noexcept {
818 if (
this == &other || context_ == other.context_) {
823 context_.swap(other.context_);
830 context_pointer_type context;
831 context.swap(context_);
832 size_t future_counter = --context->future_counter_;
834 if (0 == future_counter) {
835 context->force_finish();
840 size_t get_ref_future_count() const noexcept {
842 return context_->future_counter_.load();
848 inline task_status_type get_status() const noexcept {
850 return task_status_type::kInvalid;
853 return context_->get_status();
857 inline bool is_completed() const noexcept {
858 if (
false == is_exiting()) {
866 auto& handle = context_->get_handle_delegate().handle;
875 auto promise = context_->get_handle_delegate().promise;
880 if (promise->check_flag(promise_flag::kHasReturned)) {
890 task_status_type status = get_status();
891 return task_status_type::kDone <= status || task_status_type::kInvalid == status;
895 return LIBCOPP_COPP_NAMESPACE_ID::promise_base_type::pick_current_status();
908 bool start() noexcept {
913 LIBCOPP_COPP_NAMESPACE_ID::util::lock::lock_holder<
914 LIBCOPP_COPP_NAMESPACE_ID::util::lock::spin_lock,
915 LIBCOPP_COPP_NAMESPACE_ID::util::lock::detail::default_try_lock_action<
916 LIBCOPP_COPP_NAMESPACE_ID::util::lock::spin_lock>,
917 LIBCOPP_COPP_NAMESPACE_ID::util::lock::detail::default_try_unlock_action<
918 LIBCOPP_COPP_NAMESPACE_ID::util::lock::spin_lock>>
919 lock_holder{context_->internal_operation_lock_};
921 if (!lock_holder.is_available()) {
925 auto& handle = context_->get_handle_delegate().handle;
934 auto promise = context_->get_handle_delegate().promise;
939 task_status_type expect_status = task_status_type::kCreated;
940 if (!promise->set_status(task_status_type::kRunning, &expect_status)) {
946 if (!promise->check_flag(promise_flag::kHasReturned) && !promise->check_flag(promise_flag::kDestroying)) {
949# if 0 && defined(LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR) && LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR
950 std::exception_ptr unhandled_exception;
956# if 0 && defined(LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR) && LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR
958 unhandled_exception = std::current_exception();
974 bool kill(task_status_type target_status = task_status_type::kKilled,
bool force_resume =
false) noexcept {
975 if (target_status < task_status_type::kDone) {
983 LIBCOPP_COPP_NAMESPACE_ID::util::lock::lock_holder<
984 LIBCOPP_COPP_NAMESPACE_ID::util::lock::spin_lock,
985 LIBCOPP_COPP_NAMESPACE_ID::util::lock::detail::default_try_lock_action<
986 LIBCOPP_COPP_NAMESPACE_ID::util::lock::spin_lock>,
987 LIBCOPP_COPP_NAMESPACE_ID::util::lock::detail::default_try_unlock_action<
988 LIBCOPP_COPP_NAMESPACE_ID::util::lock::spin_lock>>
989 lock_holder{context_->internal_operation_lock_};
991 if (!lock_holder.is_available()) {
995 auto& handle = context_->get_handle_delegate().handle;
1007 if (handle.done()) {
1012 task_status_type current_status = get_status();
1013 if (current_status >= task_status_type::kDone) {
1018 auto promise = context_->get_handle_delegate().promise;
1023 if (!promise->set_status(target_status, ¤t_status)) {
1027 if ((force_resume || promise->is_waiting()) && !promise->check_flag(promise_flag::kHasReturned) &&
1028 !promise->check_flag(promise_flag::kDestroying)) {
1031# if 0 && defined(LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR) && LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR
1032 std::exception_ptr unhandled_exception;
1038# if 0 && defined(LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR) && LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR
1041 unhandled_exception = std::current_exception();
1054 return kill(task_status_type::kCancle, force_resume);
1061 inline id_type get_id() const noexcept {
1066 return context_->get_id();
1072 context_pointer_type context_;
1075template <
class TVALUE,
class TPRIVATE_DATA,
class TERROR_TRANSFORM,
bool NO_PRIVATE_DATA>
1076class LIBCOPP_COTASK_API_HEAD_ONLY task_future_delegate;
1078template <
class TVALUE,
class TPRIVATE_DATA,
class TERROR_TRANSFORM>
1079class LIBCOPP_COTASK_API_HEAD_ONLY task_future_delegate<TVALUE, TPRIVATE_DATA, TERROR_TRANSFORM, false>
1080 :
public task_future_base<TVALUE, TPRIVATE_DATA, TERROR_TRANSFORM> {
1082 using base_type = task_future_base<TVALUE, TPRIVATE_DATA, TERROR_TRANSFORM>;
1083 using value_type =
typename base_type::value_type;
1084 using context_type =
typename base_type::context_type;
1085 using id_type =
typename base_type::id_type;
1086 using private_data_type =
typename base_type::private_data_type;
1087 using context_pointer_type =
typename base_type::context_pointer_type;
1088 using task_status_type =
typename base_type::task_status_type;
1089 using promise_flag =
typename base_type::promise_flag;
1092 task_future_delegate() noexcept = default;
1093 task_future_delegate(context_pointer_type context) noexcept : base_type{context} {}
1094 task_future_delegate(
const task_future_delegate& other) noexcept : base_type{other} {}
1095 task_future_delegate(task_future_delegate&& other) noexcept : base_type{std::move(other)} {}
1096 task_future_delegate& operator=(
const task_future_delegate& other)
noexcept {
1101 task_future_delegate& operator=(task_future_delegate&& other)
noexcept {
1102 assign(std::move(other));
1106 using base_type::assign;
1107 using base_type::get_context;
1109 inline private_data_type* get_private_data() noexcept {
1114 return &get_context()->get_private_data();
1117 inline const private_data_type* get_private_data() const noexcept {
1122 return &get_context()->get_private_data();
1126template <
class TVALUE,
class TPRIVATE_DATA,
class TERROR_TRANSFORM>
1127class LIBCOPP_COTASK_API_HEAD_ONLY task_future_delegate<TVALUE, TPRIVATE_DATA, TERROR_TRANSFORM, true>
1128 :
public task_future_base<TVALUE, TPRIVATE_DATA, TERROR_TRANSFORM> {
1130 using base_type = task_future_base<TVALUE, TPRIVATE_DATA, TERROR_TRANSFORM>;
1131 using value_type =
typename base_type::value_type;
1132 using context_type =
typename base_type::context_type;
1133 using id_type =
typename base_type::id_type;
1134 using private_data_type =
typename base_type::private_data_type;
1135 using context_pointer_type =
typename base_type::context_pointer_type;
1136 using task_status_type =
typename base_type::task_status_type;
1137 using promise_flag =
typename base_type::promise_flag;
1140 task_future_delegate() noexcept = default;
1141 task_future_delegate(context_pointer_type context) noexcept : base_type{context} {}
1142 task_future_delegate(
const task_future_delegate& other) noexcept : base_type{other} {}
1143 task_future_delegate(task_future_delegate&& other) noexcept : base_type{std::move(other)} {}
1144 task_future_delegate& operator=(
const task_future_delegate& other)
noexcept {
1149 task_future_delegate& operator=(task_future_delegate&& other)
noexcept {
1150 assign(std::move(other));
1154 using base_type::assign;
1155 using base_type::get_context;
1158template <
class TVALUE,
class TPRIVATE_DATA,
1159 class TERROR_TRANSFORM = LIBCOPP_COPP_NAMESPACE_ID::promise_error_transform<TVALUE>>
1160class LIBCOPP_COTASK_API_HEAD_ONLY task_future
1161 :
public task_future_delegate<TVALUE, TPRIVATE_DATA, TERROR_TRANSFORM, std::is_same<TPRIVATE_DATA, void>::value> {
1163 using error_transform = TERROR_TRANSFORM;
1164 using self_type = task_future<TVALUE, TPRIVATE_DATA, error_transform>;
1166 task_future_delegate<TVALUE, TPRIVATE_DATA, error_transform, std::is_same<TPRIVATE_DATA, void>::value>;
1167 using value_type =
typename base_type::value_type;
1168 using context_type =
typename base_type::context_type;
1169 using id_type =
typename base_type::id_type;
1170 using private_data_type =
typename base_type::private_data_type;
1171 using context_pointer_type =
typename base_type::context_pointer_type;
1172 using task_status_type =
typename base_type::task_status_type;
1173 using promise_flag =
typename base_type::promise_flag;
1175 using promise_base_type = task_promise_base<
value_type, private_data_type, error_transform,
1176 std::is_void<typename std::decay<value_type>::type>::value>;
1177 class promise_type :
public promise_base_type {
1179# if defined(__GNUC__) && !defined(__clang__)
1180 template <
class... TARGS>
1181 promise_type(TARGS&&... args) : promise_base_type(args...) {}
1183 template <
class... TARGS>
1184 promise_type(TARGS&&... args) : promise_base_type(
std::forward<TARGS>(args)...) {}
1187 using promise_base_type::get_context;
1188 using promise_base_type::move_context;
1190 auto get_return_object() noexcept {
return self_type{get_context()}; }
1192 struct initial_awaitable {
1193 inline bool await_ready() const noexcept {
return false; }
1195 inline void await_resume() const noexcept {
1196 if (handle.promise().get_status() == task_status_type::kCreated) {
1197 task_status_type excepted = task_status_type::kCreated;
1198 handle.promise().set_status(task_status_type::kRunning, &excepted);
1204 caller.promise().initialize_promise(caller);
1209 initial_awaitable initial_suspend() noexcept {
return {}; }
1212 struct LIBCOPP_COTASK_API_HEAD_ONLY final_awaitable
1213 :
public LIBCOPP_COPP_NAMESPACE_ID::promise_base_type::final_awaitable {
1214# if defined(LIBCOPP_MACRO_ENABLE_CONCEPTS) && LIBCOPP_MACRO_ENABLE_CONCEPTS
1215 template <std::derived_from<promise_base_type> TPROMISE>
1217 template <class TPROMISE, typename = std::enable_if_t<std::is_base_of<promise_base_type, TPROMISE>::value>>
1221 context_pointer_type context = self.promise().move_context();
1223# if defined(LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER) && LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER
1224 context->unbind_from_manager();
1228 LIBCOPP_COPP_NAMESPACE_ID::promise_base_type::final_awaitable::await_suspend(self);
1234 final_awaitable final_suspend() noexcept {
return {}; }
1236# if defined(LIBCOPP_MACRO_ENABLE_EXCEPTION) && LIBCOPP_MACRO_ENABLE_EXCEPTION
1237 void unhandled_exception() {
1242 void unhandled_exception() { std::abort(); }
1245 template <
class TCONVERT_PRIVATE_DATA>
1246 inline task_private_data<TCONVERT_PRIVATE_DATA> yield_value(
1247 task_private_data<TCONVERT_PRIVATE_DATA>&& input)
noexcept {
1248 if (get_context()) {
1249 input.data_ = &get_context()->get_private_data();
1251 input.data_ =
nullptr;
1253 return task_private_data<TCONVERT_PRIVATE_DATA>(input.data_);
1256 inline task_pick_id<id_type> yield_value(task_pick_id<id_type>&& input)
noexcept {
1257 if (get_context()) {
1258 input.data_ = get_context()->get_id();
1262 return task_pick_id<id_type>(input.data_);
1265 using promise_base_type::yield_value;
1268 using awaitable_type = task_awaitable<context_type, std::is_void<typename std::decay<value_type>::type>::value>;
1270# if defined(LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER) && LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER
1271 using task_manager_helper =
typename context_type::task_manager_helper;
1275 task_future() noexcept = default;
1276 task_future(context_pointer_type context) noexcept : base_type{context} {}
1277 task_future(
const task_future& other) noexcept : base_type{other} {}
1278 task_future(task_future&& other) noexcept : base_type{std::move(other)} {}
1279 task_future& operator=(
const task_future& other)
noexcept {
1284 task_future& operator=(task_future&& other)
noexcept {
1285 assign(std::move(other));
1289 using base_type::assign;
1290 using base_type::get_context;
1292 inline awaitable_type
operator co_await() {
return awaitable_type{get_context().get()}; }
1295 template <
class TTHENABLE_VALUE>
1296 struct _thenable_return_traits_value_type;
1298 template <
class TCALLABLE_VALUE,
class TTASK_ERROR_TRANSFORM>
1299 struct _thenable_return_traits_value_type<
1300 LIBCOPP_COPP_NAMESPACE_ID::callable_future<TCALLABLE_VALUE, TTASK_ERROR_TRANSFORM>> :
public std::true_type {
1302 typename LIBCOPP_COPP_NAMESPACE_ID::callable_future<TCALLABLE_VALUE, TTASK_ERROR_TRANSFORM>::value_type;
1303 using error_transform = TTASK_ERROR_TRANSFORM;
1305 template <
class TINPUT>
1307 start_thenable(TINPUT&& c) {
1308 return {std::forward<TINPUT>(c)};
1312 template <
class TTASK_VALUE,
class TTASK_PRIVATE_DATA,
class TTASK_ERROR_TRANSFORM>
1313 struct _thenable_return_traits_value_type<task_future<TTASK_VALUE, TTASK_PRIVATE_DATA, TTASK_ERROR_TRANSFORM>>
1314 :
public std::true_type {
1315 using type =
typename task_future<TTASK_VALUE, TTASK_PRIVATE_DATA, TTASK_ERROR_TRANSFORM>::value_type;
1316 using error_transform = TTASK_ERROR_TRANSFORM;
1318 template <
class TINPUT>
1319 LIBCOPP_UTIL_FORCEINLINE static task_future<TTASK_VALUE, TTASK_PRIVATE_DATA, TTASK_ERROR_TRANSFORM> start_thenable(
1322 return {std::forward<TINPUT>(
task)};
1326 template <
class TTHENABLE_VALUE>
1327 struct _thenable_return_traits_value_type :
public std::false_type {
1328 using type = TTHENABLE_VALUE;
1331 template <
class TTHENABLE,
bool TASK_RETURN_VOID>
1332 struct _thenable_return_traits_return_type;
1334 template <
class TTHENABLE>
1335 struct _thenable_return_traits_return_type<TTHENABLE, true>
1336 :
public _thenable_return_traits_value_type<typename std::invoke_result<TTHENABLE, context_pointer_type>::type> {
1339 template <
class TTHENABLE>
1340 struct _thenable_return_traits_return_type<TTHENABLE, false>
1341 :
public _thenable_return_traits_value_type<
1342 typename std::invoke_result<TTHENABLE, context_pointer_type, value_type>::type> {};
1344 template <
class TTHENABLE>
1345 struct thenable_return_traits
1346 :
public _thenable_return_traits_return_type<TTHENABLE, std::is_void<value_type>::value> {};
1348 template <
class TTHENABLE,
bool THENABLE_RETURN_COROUTINE>
1349 struct _thenable_default_error_transform;
1351 template <
class TTHENABLE>
1352 struct _thenable_default_error_transform<TTHENABLE, true> {
1353 using type =
typename thenable_return_traits<TTHENABLE>::error_transform;
1356 template <
class TTHENABLE>
1357 struct _thenable_default_error_transform<TTHENABLE, false> {
1358 using type = LIBCOPP_COPP_NAMESPACE_ID::promise_error_transform<typename thenable_return_traits<TTHENABLE>::type>;
1361 template <
class TTHENABLE>
1362 struct thenable_error_transform_traits
1363 :
public _thenable_default_error_transform<TTHENABLE, thenable_return_traits<TTHENABLE>::value> {};
1365 template <
class TTHENABLE,
class TTHENABLE_ERROR_TRANSFORM,
bool THENABLE_RETURN_COROUTINE,
bool THENABLE_RETURN_VOID,
1366 bool TASK_RETURN_VOID>
1367 struct thenable_traits;
1369 template <
class TTHENABLE,
class TTHENABLE_ERROR_TRANSFORM>
1370 struct thenable_traits<TTHENABLE, TTHENABLE_ERROR_TRANSFORM, true, false, false> {
1371 using callable_thenable_type =
1372 LIBCOPP_COPP_NAMESPACE_ID::callable_future<typename thenable_return_traits<TTHENABLE>::type,
1373 TTHENABLE_ERROR_TRANSFORM>;
1375 template <
class TTHENABLE_PRIVATE_DATA>
1376 struct task_thenable_type {
1377 using task_type = task_future<typename thenable_return_traits<TTHENABLE>::type, TTHENABLE_PRIVATE_DATA,
1378 TTHENABLE_ERROR_TRANSFORM>;
1381 inline static callable_thenable_type invoke_callable(self_type self, TTHENABLE thenable) {
1382 co_return (
co_await thenable_return_traits<TTHENABLE>::start_thenable(
1383 thenable(context_pointer_type(self.get_context()),
co_await self)));
1386 template <
class TTHENABLE_PRIVATE_DATA>
1387 inline static typename task_thenable_type<TTHENABLE_PRIVATE_DATA>::task_type invoke_task(self_type self,
1388 TTHENABLE thenable) {
1389 co_return (
co_await thenable_return_traits<TTHENABLE>::start_thenable(
1390 thenable(context_pointer_type(self.get_context()),
co_await self)));
1394 template <
class TTHENABLE,
class TTHENABLE_ERROR_TRANSFORM>
1395 struct thenable_traits<TTHENABLE, TTHENABLE_ERROR_TRANSFORM, true, false, true> {
1396 using callable_thenable_type =
1397 LIBCOPP_COPP_NAMESPACE_ID::callable_future<typename thenable_return_traits<TTHENABLE>::type,
1398 TTHENABLE_ERROR_TRANSFORM>;
1400 template <
class TTHENABLE_PRIVATE_DATA>
1401 struct task_thenable_type {
1402 using task_type = task_future<typename thenable_return_traits<TTHENABLE>::type, TTHENABLE_PRIVATE_DATA,
1403 TTHENABLE_ERROR_TRANSFORM>;
1406 inline static callable_thenable_type invoke_callable(self_type self, TTHENABLE thenable) {
1408 co_return (
co_await thenable_return_traits<TTHENABLE>::start_thenable(
1409 thenable(context_pointer_type(self.get_context()))));
1412 template <
class TTHENABLE_PRIVATE_DATA>
1413 inline static typename task_thenable_type<TTHENABLE_PRIVATE_DATA>::task_type invoke_task(self_type self,
1414 TTHENABLE thenable) {
1416 co_return (
co_await thenable_return_traits<TTHENABLE>::start_thenable(
1417 thenable(context_pointer_type(self.get_context()))));
1421 template <
class TTHENABLE,
class TTHENABLE_ERROR_TRANSFORM>
1422 struct thenable_traits<TTHENABLE, TTHENABLE_ERROR_TRANSFORM, true, true, false> {
1423 using callable_thenable_type =
1424 LIBCOPP_COPP_NAMESPACE_ID::callable_future<typename thenable_return_traits<TTHENABLE>::type,
1425 TTHENABLE_ERROR_TRANSFORM>;
1427 template <
class TTHENABLE_PRIVATE_DATA>
1428 struct task_thenable_type {
1429 using task_type = task_future<typename thenable_return_traits<TTHENABLE>::type, TTHENABLE_PRIVATE_DATA,
1430 TTHENABLE_ERROR_TRANSFORM>;
1433 inline static callable_thenable_type invoke_callable(self_type self, TTHENABLE thenable) {
1434 co_await thenable_return_traits<TTHENABLE>::start_thenable(
1435 thenable(context_pointer_type(self.get_context()),
co_await self));
1439 template <
class TTHENABLE_PRIVATE_DATA>
1440 inline static typename task_thenable_type<TTHENABLE_PRIVATE_DATA>::task_type invoke_task(self_type self,
1441 TTHENABLE thenable) {
1442 co_await thenable_return_traits<TTHENABLE>::start_thenable(
1443 thenable(context_pointer_type(self.get_context()),
co_await self));
1448 template <
class TTHENABLE,
class TTHENABLE_ERROR_TRANSFORM>
1449 struct thenable_traits<TTHENABLE, TTHENABLE_ERROR_TRANSFORM, true, true, true> {
1450 using callable_thenable_type =
1451 LIBCOPP_COPP_NAMESPACE_ID::callable_future<typename thenable_return_traits<TTHENABLE>::type,
1452 TTHENABLE_ERROR_TRANSFORM>;
1454 template <
class TTHENABLE_PRIVATE_DATA>
1455 struct task_thenable_type {
1456 using task_type = task_future<typename thenable_return_traits<TTHENABLE>::type, TTHENABLE_PRIVATE_DATA,
1457 TTHENABLE_ERROR_TRANSFORM>;
1460 inline static callable_thenable_type invoke_callable(self_type self, TTHENABLE thenable) {
1462 co_await thenable_return_traits<TTHENABLE>::start_thenable(thenable(context_pointer_type(self.get_context())));
1466 template <
class TTHENABLE_PRIVATE_DATA>
1467 inline static typename task_thenable_type<TTHENABLE_PRIVATE_DATA>::task_type invoke_task(self_type self,
1468 TTHENABLE thenable) {
1470 co_await thenable_return_traits<TTHENABLE>::start_thenable(thenable(context_pointer_type(self.get_context())));
1475 template <
class TTHENABLE,
class TTHENABLE_ERROR_TRANSFORM>
1476 struct thenable_traits<TTHENABLE, TTHENABLE_ERROR_TRANSFORM, false, true, false> {
1477 using callable_thenable_type =
1478 LIBCOPP_COPP_NAMESPACE_ID::callable_future<typename thenable_return_traits<TTHENABLE>::type,
1479 TTHENABLE_ERROR_TRANSFORM>;
1481 template <
class TTHENABLE_PRIVATE_DATA>
1482 struct task_thenable_type {
1483 using task_type = task_future<typename thenable_return_traits<TTHENABLE>::type, TTHENABLE_PRIVATE_DATA,
1484 TTHENABLE_ERROR_TRANSFORM>;
1487 inline static callable_thenable_type invoke_callable(self_type self, TTHENABLE thenable) {
1488 thenable(context_pointer_type(self.get_context()),
co_await self);
1492 template <
class TTHENABLE_PRIVATE_DATA>
1493 inline static typename task_thenable_type<TTHENABLE_PRIVATE_DATA>::task_type invoke_task(self_type self,
1494 TTHENABLE thenable) {
1495 thenable(context_pointer_type(self.get_context()),
co_await self);
1500 template <
class TTHENABLE,
class TTHENABLE_ERROR_TRANSFORM>
1501 struct thenable_traits<TTHENABLE, TTHENABLE_ERROR_TRANSFORM, false, true, true> {
1502 using callable_thenable_type =
1503 LIBCOPP_COPP_NAMESPACE_ID::callable_future<typename thenable_return_traits<TTHENABLE>::type,
1504 TTHENABLE_ERROR_TRANSFORM>;
1506 template <
class TTHENABLE_PRIVATE_DATA>
1507 struct task_thenable_type {
1508 using task_type = task_future<typename thenable_return_traits<TTHENABLE>::type, TTHENABLE_PRIVATE_DATA,
1509 TTHENABLE_ERROR_TRANSFORM>;
1512 inline static callable_thenable_type invoke_callable(self_type self, TTHENABLE thenable) {
1514 thenable(context_pointer_type(self.get_context()));
1518 template <
class TTHENABLE_PRIVATE_DATA>
1519 inline static typename task_thenable_type<TTHENABLE_PRIVATE_DATA>::task_type invoke_task(self_type self,
1520 TTHENABLE thenable) {
1522 thenable(context_pointer_type(self.get_context()));
1527 template <
class TTHENABLE,
class TTHENABLE_ERROR_TRANSFORM>
1528 struct thenable_traits<TTHENABLE, TTHENABLE_ERROR_TRANSFORM, false, false, false> {
1529 using callable_thenable_type =
1530 LIBCOPP_COPP_NAMESPACE_ID::callable_future<typename thenable_return_traits<TTHENABLE>::type,
1531 TTHENABLE_ERROR_TRANSFORM>;
1533 template <
class TTHENABLE_PRIVATE_DATA>
1534 struct task_thenable_type {
1535 using task_type = task_future<typename thenable_return_traits<TTHENABLE>::type, TTHENABLE_PRIVATE_DATA,
1536 TTHENABLE_ERROR_TRANSFORM>;
1539 inline static callable_thenable_type invoke_callable(self_type self, TTHENABLE thenable) {
1540 co_return thenable(context_pointer_type(self.get_context()),
co_await self);
1543 template <
class TTHENABLE_PRIVATE_DATA>
1544 inline static typename task_thenable_type<TTHENABLE_PRIVATE_DATA>::task_type invoke_task(self_type self,
1545 TTHENABLE thenable) {
1546 co_return thenable(context_pointer_type(self.get_context()),
co_await self);
1550 template <
class TTHENABLE,
class TTHENABLE_ERROR_TRANSFORM>
1551 struct thenable_traits<TTHENABLE, TTHENABLE_ERROR_TRANSFORM, false, false, true> {
1552 using callable_thenable_type =
1553 LIBCOPP_COPP_NAMESPACE_ID::callable_future<typename thenable_return_traits<TTHENABLE>::type,
1554 TTHENABLE_ERROR_TRANSFORM>;
1556 template <
class TTHENABLE_PRIVATE_DATA>
1557 struct task_thenable_type {
1558 using task_type = task_future<typename thenable_return_traits<TTHENABLE>::type, TTHENABLE_PRIVATE_DATA,
1559 TTHENABLE_ERROR_TRANSFORM>;
1562 inline static callable_thenable_type invoke_callable(self_type self, TTHENABLE thenable) {
1564 co_return thenable(context_pointer_type(self.get_context()));
1567 template <
class TTHENABLE_PRIVATE_DATA>
1568 inline static typename task_thenable_type<TTHENABLE_PRIVATE_DATA>::task_type invoke_task(self_type self,
1569 TTHENABLE thenable) {
1571 co_return thenable(context_pointer_type(self.get_context()));
1576 template <
class TTHENABLE,
class TTHENABLE_ERROR_TRANSFORM>
1577 struct callable_thenable_trait {
1578 using trait_type = thenable_traits<
1579 typename std::decay<TTHENABLE>::type, TTHENABLE_ERROR_TRANSFORM,
1580 thenable_return_traits<typename std::decay<TTHENABLE>::type>::value,
1581 std::is_same<typename thenable_return_traits<typename std::decay<TTHENABLE>::type>::type,
void>::value,
1582 std::is_void<value_type>::value>;
1584 using callable_thenable_type =
typename trait_type::callable_thenable_type;
1587 template <
class TTHENABLE,
class TTHENABLE_PRIVATE_DATA,
class TTHENABLE_ERROR_TRANSFORM>
1588 struct task_thenable_trait {
1589 using trait_type = thenable_traits<
1590 typename std::decay<TTHENABLE>::type, TTHENABLE_ERROR_TRANSFORM,
1591 thenable_return_traits<typename std::decay<TTHENABLE>::type>::value,
1592 std::is_same<typename thenable_return_traits<typename std::decay<TTHENABLE>::type>::type,
void>::value,
1593 std::is_void<value_type>::value>;
1595 using task_thenable_wrapper =
typename trait_type::template task_thenable_type<TTHENABLE_PRIVATE_DATA>;
1596 using task_thenable_type =
typename task_thenable_wrapper::task_type;
1620 template <
class TTHENABLE,
1621 class TTHENABLE_ERROR_TRANSFORM =
typename thenable_error_transform_traits<TTHENABLE>::type>
1622 typename callable_thenable_trait<TTHENABLE, TTHENABLE_ERROR_TRANSFORM>::callable_thenable_type then(
1623 TTHENABLE&& thenable) {
1624 using trait_type =
typename callable_thenable_trait<TTHENABLE, TTHENABLE_ERROR_TRANSFORM>::trait_type;
1625 return trait_type::invoke_callable(*
this, std::forward<TTHENABLE>(thenable));
1654 template <
class TTHENABLE,
class TTHENABLE_PRIVATE_DATA,
1655 class TTHENABLE_ERROR_TRANSFORM =
typename thenable_error_transform_traits<TTHENABLE>::type>
1656 typename task_thenable_trait<TTHENABLE, typename std::decay<TTHENABLE_PRIVATE_DATA>::type,
1657 TTHENABLE_ERROR_TRANSFORM>::task_thenable_type
1658 then(TTHENABLE&& thenable, TTHENABLE_PRIVATE_DATA&& private_data) {
1659 using trait_type =
typename task_thenable_trait<TTHENABLE, typename std::decay<TTHENABLE_PRIVATE_DATA>::type,
1660 TTHENABLE_ERROR_TRANSFORM>::trait_type;
1661 auto result = trait_type::template invoke_task<typename std::decay<TTHENABLE_PRIVATE_DATA>::type>(
1662 *
this, std::forward<TTHENABLE>(thenable));
1663 *result.get_private_data() = std::forward<TTHENABLE_PRIVATE_DATA>(private_data);
1694 template <
class TTHENABLE,
1695 class TTHENABLE_ERROR_TRANSFORM =
typename thenable_error_transform_traits<TTHENABLE>::type>
1696 typename task_thenable_trait<TTHENABLE, void, TTHENABLE_ERROR_TRANSFORM>::task_thenable_type then(
1697 TTHENABLE&& thenable, std::nullptr_t) {
1698 using trait_type =
typename task_thenable_trait<TTHENABLE, void, TTHENABLE_ERROR_TRANSFORM>::trait_type;
1699 auto result = trait_type::template invoke_task<void>(*
this, std::forward<TTHENABLE>(thenable));
1706template <
class TVALUE,
class TPRIVATE_DATA,
class TERROR_TRANSFORM>
1707struct LIBCOPP_COTASK_API_HEAD_ONLY some_delegate_task_action {
1708 using future_type = task_future<TVALUE, TPRIVATE_DATA, TERROR_TRANSFORM>;
1709 using context_type = LIBCOPP_COPP_NAMESPACE_ID::some_delegate_context<future_type>;
1711 inline static void suspend_future(
const LIBCOPP_COPP_NAMESPACE_ID::promise_caller_manager::handle_delegate& caller,
1712 future_type& task_object) {
1713 if (task_object.get_context()) {
1714 task_object.get_context()->add_caller(caller);
1718 inline static void resume_future(
const LIBCOPP_COPP_NAMESPACE_ID::promise_caller_manager::handle_delegate& caller,
1719 future_type& task_object) {
1720 if (task_object.get_context()) {
1721 task_object.get_context()->remove_caller(caller);
1725 inline static bool is_pending(future_type& future_object)
noexcept {
return !future_object.is_exiting(); }
1728LIBCOPP_COTASK_NAMESPACE_END
1730LIBCOPP_COPP_NAMESPACE_BEGIN
1732template <
class TVALUE,
class TPRIVATE_DATA,
class TERROR_TRANSFORM>
1733class LIBCOPP_COTASK_API_HEAD_ONLY some_delegate<cotask::task_future<TVALUE, TPRIVATE_DATA, TERROR_TRANSFORM>>
1734 :
public some_delegate_base<cotask::task_future<TVALUE, TPRIVATE_DATA, TERROR_TRANSFORM>,
1735 cotask::some_delegate_task_action<TVALUE, TPRIVATE_DATA, TERROR_TRANSFORM>> {
1737 using base_type = some_delegate_base<cotask::task_future<TVALUE, TPRIVATE_DATA, TERROR_TRANSFORM>,
1738 cotask::some_delegate_task_action<TVALUE, TPRIVATE_DATA, TERROR_TRANSFORM>>;
1739 using future_type =
typename base_type::future_type;
1740 using value_type =
typename base_type::value_type;
1741 using ready_output_type =
typename base_type::ready_output_type;
1742 using context_type =
typename base_type::context_type;
1744 using base_type::run;
1747LIBCOPP_COPP_NAMESPACE_END
int start(void *priv_data, EN_TASK_STATUS expected_status=EN_TS_CREATED) override
#define LIBCOPP_UTIL_FORCEINLINE
#define LIBCOPP_UTIL_LIKELY_CONDITION(__C)
#define LIBCOPP_UTIL_UNLIKELY_CONDITION(__C)
#define LIBCOPP_MACRO_STD_COROUTINE_NAMESPACE
锁管理器 Licensed under the MIT licenses.
auto operator==(const not_null< T > &lhs, const not_null< U > &rhs) noexcept(noexcept(lhs.get()==rhs.get())) -> decltype(lhs.get()==rhs.get())
auto operator!=(const not_null< T > &lhs, const not_null< U > &rhs) noexcept(noexcept(lhs.get() !=rhs.get())) -> decltype(lhs.get() !=rhs.get())
constexpr auto data(TCONTAINER &&container) -> decltype(container.data())
LIBCOPP_UTIL_FORCEINLINE default_strong_rc_ptr< T > default_make_strong(ArgsT &&... args)
assign_t< T > assign(T &t)
std::shared_ptr< cli::cmd_option_value > value_type
自旋锁 Licensed under the MIT licenses.
class LIBCOPP_COTASK_API_HEAD_ONLY task_manager