5 #include <libcopp/utils/config/libcopp_build_features.h>
21 #include <type_traits>
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
32 LIBCOPP_COTASK_NAMESPACE_BEGIN
34 template <
class TVALUE>
35 class LIBCOPP_COTASK_API_HEAD_ONLY task_context_base;
37 template <
class TVALUE,
class TERROR_TRANSFORM,
bool RETURN_VOID>
38 class LIBCOPP_COTASK_API_HEAD_ONLY task_context_delegate;
40 template <
class TVALUE,
class TPRIVATE_DATA,
class TERROR_TRANSFORM>
41 class LIBCOPP_COTASK_API_HEAD_ONLY task_context;
43 template <
class TVALUE,
class TPRIVATE_DATA,
class TERROR_TRANSFORM>
44 class LIBCOPP_COTASK_API_HEAD_ONLY task_future_base;
46 template <
class TVALUE,
class TPRIVATE_DATA,
class TERROR_TRANSFORM>
47 class LIBCOPP_COTASK_API_HEAD_ONLY task_future;
49 template <
class TVALUE,
class TPRIVATE_DATA,
class TERROR_TRANSFORM,
bool RETURN_VOID>
50 class LIBCOPP_COTASK_API_HEAD_ONLY task_promise_base;
52 template <
class TCONTEXT>
53 class LIBCOPP_COTASK_API_HEAD_ONLY task_awaitable_base;
55 template <
class TCONTEXT,
bool RETURN_VOID>
56 class LIBCOPP_COTASK_API_HEAD_ONLY task_awaitable;
58 template <
class TVALUE>
59 class LIBCOPP_COTASK_API_HEAD_ONLY task_context_base {
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();
209 UTIL_FORCEINLINE void initialize_handle(handle_delegate handle) noexcept { current_handle_ = handle; }
211 UTIL_FORCEINLINE handle_delegate& get_handle_delegate() noexcept {
return current_handle_; }
212 UTIL_FORCEINLINE const handle_delegate& get_handle_delegate()
const noexcept {
return current_handle_; }
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 defined(LIBCOPP_LOCK_DISABLE_MT) && LIBCOPP_LOCK_DISABLE_MT
250 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>&);
264 template <
class TVALUE,
class TERROR_TRANSFORM>
265 class 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;
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;
302 template <
class TVALUE,
class TERROR_TRANSFORM>
303 class 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;
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;
363 template <
class TPRIVATE_DATA>
364 class 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_;
389 class 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;
413 template <
class TVALUE,
class TERROR_TRANSFORM>
414 class 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>;
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&&...) {}
436 template <
class TVALUE,
class TPRIVATE_DATA,
class TERROR_TRANSFORM>
437 class 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>;
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_;
468 template <
class TVALUE,
class TPRIVATE_DATA,
class TERROR_TRANSFORM>
469 class 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 = std::shared_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_(std::make_shared<context_type>(std::forward<TARGS>(args)...)) {}
483 void return_void() noexcept {
484 set_flag(LIBCOPP_COPP_NAMESPACE_ID::promise_flag::kHasReturned,
true);
486 if (get_status() < task_status_type::kDone) {
487 set_status(task_status_type::kDone);
491 get_context()->set_value();
497 context_pointer_type ret = std::move(context_strong_ref_);
498 context_strong_ref_.reset();
502 UTIL_FORCEINLINE const context_pointer_type& get_context() noexcept {
return context_strong_ref_; }
504 template <
class TPROMISE,
typename = std::enable_if_t<std::is_base_of<
505 task_promise_base<TVALUE, TPRIVATE_DATA, TERROR_TRANSFORM, true>, TPROMISE>::value>>
509 get_context()->initialize_handle(handle_delegate{origin_handle});
514 context_pointer_type context_strong_ref_;
517 template <
class TVALUE,
class TPRIVATE_DATA,
class TERROR_TRANSFORM>
518 class LIBCOPP_COTASK_API_HEAD_ONLY task_promise_base<TVALUE, TPRIVATE_DATA, TERROR_TRANSFORM, false>
519 :
public LIBCOPP_COPP_NAMESPACE_ID::promise_base_type {
522 using context_type = task_context<value_type, TPRIVATE_DATA, TERROR_TRANSFORM>;
523 using private_data_type =
typename context_type::private_data_type;
524 using context_pointer_type = std::shared_ptr<context_type>;
525 using task_status_type = LIBCOPP_COPP_NAMESPACE_ID::promise_status;
527 template <
class... TARGS>
528 task_promise_base(TARGS&&... args)
529 : context_strong_ref_(std::make_shared<context_type>(std::forward<TARGS>(args)...)) {}
532 set_flag(LIBCOPP_COPP_NAMESPACE_ID::promise_flag::kHasReturned,
true);
534 if (get_status() < task_status_type::kDone) {
535 set_status(task_status_type::kDone);
538 get_context()->set_value(std::move(value));
544 return get_context()->data();
551 return get_context()->data();
558 context_pointer_type ret = std::move(context_strong_ref_);
559 context_strong_ref_.reset();
563 UTIL_FORCEINLINE const context_pointer_type& get_context() noexcept {
return context_strong_ref_; }
565 template <
class TPROMISE,
typename = std::enable_if_t<std::is_base_of<
566 task_promise_base<TVALUE, TPRIVATE_DATA, TERROR_TRANSFORM, false>, TPROMISE>::value>>
570 get_context()->initialize_handle(handle_delegate{origin_handle});
575 context_pointer_type context_strong_ref_;
578 template <
class TCONTEXT>
579 class LIBCOPP_COTASK_API_HEAD_ONLY task_awaitable_base :
public LIBCOPP_COPP_NAMESPACE_ID::awaitable_base_type {
581 using context_type = TCONTEXT;
582 using context_pointer_type = std::shared_ptr<context_type>;
584 using task_status_type = LIBCOPP_COPP_NAMESPACE_ID::promise_status;
585 using promise_flag = LIBCOPP_COPP_NAMESPACE_ID::promise_flag;
588 task_awaitable_base(context_type* context) : context_{context} {}
590 inline bool await_ready() noexcept {
595 if (context_->is_ready()) {
599 if (
nullptr == context_->get_handle_delegate().promise) {
603 if (context_->get_handle_delegate().promise->get_status() >= task_status_type::kDone) {
610 # if defined(LIBCOPP_MACRO_ENABLE_CONCEPTS) && LIBCOPP_MACRO_ENABLE_CONCEPTS
611 template <LIBCOPP_COPP_NAMESPACE_ID::DerivedPromiseBaseType TCPROMISE>
613 template <
class TCPROMISE,
typename = std::enable_if_t<
614 std::is_base_of<LIBCOPP_COPP_NAMESPACE_ID::promise_base_type, TCPROMISE>::value>>
617 if (
nullptr != context_ && caller.promise().get_status() < task_status_type::kDone) {
619 context_->add_caller(caller);
622 caller.promise().set_flag(promise_flag::kInternalWaitting,
true);
632 task_status_type detach() noexcept {
633 task_status_type result_status;
635 result_status = task_status_type::kInvalid;
636 }
else if (context_->is_ready()) {
637 result_status = task_status_type::kDone;
639 result_status = task_status_type::kKilled;
643 auto caller = get_caller();
646 if (
nullptr != caller.promise) {
647 caller.promise->set_flag(promise_flag::kInternalWaitting,
false);
650 if (!context_->is_ready() &&
nullptr != caller.promise) {
651 result_status = caller.promise->get_status();
654 context_->remove_caller(caller);
661 return result_status;
673 context_type* context_;
676 template <
class TCONTEXT>
677 class LIBCOPP_COTASK_API_HEAD_ONLY task_awaitable<TCONTEXT, true> :
public task_awaitable_base<TCONTEXT> {
679 using base_type = task_awaitable_base<TCONTEXT>;
681 using context_type =
typename base_type::context_type;
682 using context_pointer_type =
typename base_type::context_pointer_type;
683 using task_status_type =
typename base_type::task_status_type;
684 using promise_flag =
typename base_type::promise_flag;
685 using error_transform =
typename context_type::error_transform;
688 using base_type::await_ready;
689 using base_type::await_suspend;
690 using base_type::get_caller;
691 using base_type::set_caller;
692 task_awaitable(context_type* context) : base_type(context) {}
694 inline void await_resume() { detach(); }
697 using base_type::detach;
698 using base_type::get_context;
701 template <
class TCONTEXT>
702 class LIBCOPP_COTASK_API_HEAD_ONLY task_awaitable<TCONTEXT, false> :
public task_awaitable_base<TCONTEXT> {
704 using base_type = task_awaitable_base<TCONTEXT>;
706 using context_type =
typename base_type::context_type;
707 using context_pointer_type =
typename base_type::context_pointer_type;
708 using task_status_type =
typename base_type::task_status_type;
709 using promise_flag =
typename base_type::promise_flag;
710 using error_transform =
typename context_type::error_transform;
713 using base_type::await_ready;
714 using base_type::await_suspend;
715 using base_type::get_caller;
716 using base_type::set_caller;
717 task_awaitable(context_type* context) : base_type(context) {}
720 bool has_multiple_callers;
722 has_multiple_callers = get_context()->has_multiple_callers();
724 has_multiple_callers =
false;
726 task_status_type result_status = detach();
728 if (task_status_type::kDone != result_status) {
729 return error_transform()(result_status);
733 if (has_multiple_callers) {
734 return *get_context()->data();
736 return LIBCOPP_COPP_NAMESPACE_ID::multiple_callers_constructor<value_type>::return_value(
737 *get_context()->
data());
740 return error_transform()(task_status_type::kInvalid);
745 using base_type::detach;
746 using base_type::get_context;
749 template <
class TVALUE,
class TPRIVATE_DATA,
class TERROR_TRANSFORM>
750 class LIBCOPP_COTASK_API_HEAD_ONLY task_future_base {
753 using context_type = task_context<value_type, TPRIVATE_DATA, TERROR_TRANSFORM>;
754 using id_type =
typename context_type::id_type;
755 using private_data_type =
typename context_type::private_data_type;
756 using context_pointer_type = std::shared_ptr<context_type>;
757 using task_status_type =
typename context_type::task_status_type;
758 using promise_flag =
typename context_type::promise_flag;
761 task_future_base() noexcept =
default;
763 task_future_base(context_pointer_type context) noexcept : context_{context} {
765 ++context_->future_counter_;
769 task_future_base(
const task_future_base& other) noexcept : context_{other.context_} {
771 ++context_->future_counter_;
775 task_future_base(task_future_base&& other) noexcept : context_{std::move(other.context_)} { other.context_.reset(); }
777 task_future_base& operator=(
const task_future_base& other) noexcept {
782 task_future_base& operator=(task_future_base&& other) noexcept {
787 ~task_future_base() {
792 inline friend bool operator==(
const task_future_base& l,
const task_future_base& r) noexcept {
793 return l.context_ == r.context_;
796 inline friend bool operator!=(
const task_future_base& l,
const task_future_base& r) noexcept {
797 return l.context_ != r.context_;
800 inline operator bool()
const noexcept {
return valid(); }
802 void assign(
const task_future_base& other) noexcept {
803 if (
this == &other || context_ == other.context_) {
810 ++other.context_->future_counter_;
812 context_ = other.context_;
815 void assign(task_future_base&& other) noexcept {
816 if (
this == &other || context_ == other.context_) {
821 context_.swap(other.context_);
828 context_pointer_type context;
829 context.swap(context_);
830 size_t future_counter = --context->future_counter_;
832 if (0 == future_counter) {
833 context->force_finish();
838 size_t get_ref_future_count()
const noexcept {
840 return context_->future_counter_.load();
846 inline task_status_type get_status()
const noexcept {
848 return task_status_type::kInvalid;
851 return context_->get_status();
854 UTIL_FORCEINLINE bool is_canceled()
const noexcept {
return task_status_type::kCancle == get_status(); }
855 inline bool is_completed()
const noexcept {
856 if (
false == is_exiting()) {
864 auto& handle = context_->get_handle_delegate().handle;
873 auto promise = context_->get_handle_delegate().promise;
878 if (promise->check_flag(promise_flag::kHasReturned)) {
885 UTIL_FORCEINLINE bool is_faulted()
const noexcept {
return task_status_type::kKilled <= get_status(); }
886 UTIL_FORCEINLINE bool is_timeout()
const noexcept {
return task_status_type::kTimeout <= get_status(); }
888 task_status_type status = get_status();
889 return task_status_type::kDone <= status || task_status_type::kInvalid == status;
893 return LIBCOPP_COPP_NAMESPACE_ID::promise_base_type::pick_current_status();
896 UTIL_FORCEINLINE static auto yield_private_data() noexcept {
return task_private_data<TPRIVATE_DATA>{}; }
898 UTIL_FORCEINLINE static auto yield_task_id() noexcept {
return task_pick_id<id_type>{}; }
906 bool start() noexcept {
911 LIBCOPP_COPP_NAMESPACE_ID::util::lock::lock_holder<
912 LIBCOPP_COPP_NAMESPACE_ID::util::lock::spin_lock,
913 LIBCOPP_COPP_NAMESPACE_ID::util::lock::detail::default_try_lock_action<
914 LIBCOPP_COPP_NAMESPACE_ID::util::lock::spin_lock>,
915 LIBCOPP_COPP_NAMESPACE_ID::util::lock::detail::default_try_unlock_action<
916 LIBCOPP_COPP_NAMESPACE_ID::util::lock::spin_lock>>
917 lock_holder{context_->internal_operation_lock_};
919 if (!lock_holder.is_available()) {
923 auto& handle = context_->get_handle_delegate().handle;
932 auto promise = context_->get_handle_delegate().promise;
937 task_status_type expect_status = task_status_type::kCreated;
938 if (!promise->set_status(task_status_type::kRunning, &expect_status)) {
944 if (!promise->check_flag(promise_flag::kHasReturned) && !promise->check_flag(promise_flag::kDestroying)) {
947 # if 0 && defined(LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR) && LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR
948 std::exception_ptr unhandled_exception;
954 # if 0 && defined(LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR) && LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR
956 unhandled_exception = std::current_exception();
972 bool kill(task_status_type target_status = task_status_type::kKilled,
bool force_resume =
false) noexcept {
973 if (target_status < task_status_type::kDone) {
981 LIBCOPP_COPP_NAMESPACE_ID::util::lock::lock_holder<
982 LIBCOPP_COPP_NAMESPACE_ID::util::lock::spin_lock,
983 LIBCOPP_COPP_NAMESPACE_ID::util::lock::detail::default_try_lock_action<
984 LIBCOPP_COPP_NAMESPACE_ID::util::lock::spin_lock>,
985 LIBCOPP_COPP_NAMESPACE_ID::util::lock::detail::default_try_unlock_action<
986 LIBCOPP_COPP_NAMESPACE_ID::util::lock::spin_lock>>
987 lock_holder{context_->internal_operation_lock_};
989 if (!lock_holder.is_available()) {
993 auto& handle = context_->get_handle_delegate().handle;
1005 if (handle.done()) {
1010 task_status_type current_status = get_status();
1011 if (current_status >= task_status_type::kDone) {
1016 auto promise = context_->get_handle_delegate().promise;
1021 if (!promise->set_status(target_status, ¤t_status)) {
1025 if ((force_resume || promise->is_waiting()) && !promise->check_flag(promise_flag::kHasReturned) &&
1026 !promise->check_flag(promise_flag::kDestroying)) {
1029 # if 0 && defined(LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR) && LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR
1030 std::exception_ptr unhandled_exception;
1036 # if 0 && defined(LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR) && LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR
1039 unhandled_exception = std::current_exception();
1049 UTIL_FORCEINLINE bool kill(
bool force_resume) {
return kill(task_status_type::kKilled, force_resume); }
1051 UTIL_FORCEINLINE bool cancel(
bool force_resume =
false) {
return kill(task_status_type::kCancle, force_resume); }
1055 UTIL_FORCEINLINE context_pointer_type& get_context() noexcept {
return context_; }
1057 inline id_type get_id()
const noexcept {
1062 return context_->get_id();
1068 context_pointer_type context_;
1071 template <
class TVALUE,
class TPRIVATE_DATA,
class TERROR_TRANSFORM,
bool NO_PRIVATE_DATA>
1072 class LIBCOPP_COTASK_API_HEAD_ONLY task_future_delegate;
1074 template <
class TVALUE,
class TPRIVATE_DATA,
class TERROR_TRANSFORM>
1075 class LIBCOPP_COTASK_API_HEAD_ONLY task_future_delegate<TVALUE, TPRIVATE_DATA, TERROR_TRANSFORM, false>
1076 :
public task_future_base<TVALUE, TPRIVATE_DATA, TERROR_TRANSFORM> {
1078 using base_type = task_future_base<TVALUE, TPRIVATE_DATA, TERROR_TRANSFORM>;
1080 using context_type =
typename base_type::context_type;
1081 using id_type =
typename base_type::id_type;
1082 using private_data_type =
typename base_type::private_data_type;
1083 using context_pointer_type =
typename base_type::context_pointer_type;
1084 using task_status_type =
typename base_type::task_status_type;
1085 using promise_flag =
typename base_type::promise_flag;
1088 task_future_delegate() noexcept =
default;
1089 task_future_delegate(context_pointer_type context) noexcept : base_type{context} {}
1090 task_future_delegate(
const task_future_delegate& other) noexcept : base_type{other} {}
1091 task_future_delegate(task_future_delegate&& other) noexcept : base_type{std::move(other)} {}
1092 task_future_delegate& operator=(
const task_future_delegate& other) noexcept {
1097 task_future_delegate& operator=(task_future_delegate&& other) noexcept {
1098 assign(std::move(other));
1103 using base_type::get_context;
1105 inline private_data_type* get_private_data() noexcept {
1110 return &get_context()->get_private_data();
1113 inline const private_data_type* get_private_data()
const noexcept {
1118 return &get_context()->get_private_data();
1122 template <
class TVALUE,
class TPRIVATE_DATA,
class TERROR_TRANSFORM>
1123 class LIBCOPP_COTASK_API_HEAD_ONLY task_future_delegate<TVALUE, TPRIVATE_DATA, TERROR_TRANSFORM, true>
1124 :
public task_future_base<TVALUE, TPRIVATE_DATA, TERROR_TRANSFORM> {
1126 using base_type = task_future_base<TVALUE, TPRIVATE_DATA, TERROR_TRANSFORM>;
1128 using context_type =
typename base_type::context_type;
1129 using id_type =
typename base_type::id_type;
1130 using private_data_type =
typename base_type::private_data_type;
1131 using context_pointer_type =
typename base_type::context_pointer_type;
1132 using task_status_type =
typename base_type::task_status_type;
1133 using promise_flag =
typename base_type::promise_flag;
1136 task_future_delegate() noexcept =
default;
1137 task_future_delegate(context_pointer_type context) noexcept : base_type{context} {}
1138 task_future_delegate(
const task_future_delegate& other) noexcept : base_type{other} {}
1139 task_future_delegate(task_future_delegate&& other) noexcept : base_type{std::move(other)} {}
1140 task_future_delegate& operator=(
const task_future_delegate& other) noexcept {
1145 task_future_delegate& operator=(task_future_delegate&& other) noexcept {
1146 assign(std::move(other));
1151 using base_type::get_context;
1154 template <
class TVALUE,
class TPRIVATE_DATA,
1155 class TERROR_TRANSFORM = LIBCOPP_COPP_NAMESPACE_ID::promise_error_transform<TVALUE>>
1156 class LIBCOPP_COTASK_API_HEAD_ONLY task_future
1157 :
public task_future_delegate<TVALUE, TPRIVATE_DATA, TERROR_TRANSFORM, std::is_same<TPRIVATE_DATA, void>::value> {
1159 using error_transform = TERROR_TRANSFORM;
1160 using self_type = task_future<TVALUE, TPRIVATE_DATA, error_transform>;
1162 task_future_delegate<TVALUE, TPRIVATE_DATA, error_transform, std::is_same<TPRIVATE_DATA, void>::value>;
1164 using context_type =
typename base_type::context_type;
1165 using id_type =
typename base_type::id_type;
1166 using private_data_type =
typename base_type::private_data_type;
1167 using context_pointer_type =
typename base_type::context_pointer_type;
1168 using task_status_type =
typename base_type::task_status_type;
1169 using promise_flag =
typename base_type::promise_flag;
1171 using promise_base_type = task_promise_base<
value_type, private_data_type, error_transform,
1172 std::is_void<typename std::decay<value_type>::type>::value>;
1173 class promise_type :
public promise_base_type {
1175 # if defined(__GNUC__) && !defined(__clang__)
1176 template <
class... TARGS>
1177 promise_type(TARGS&&... args) : promise_base_type(args...) {}
1179 template <
class... TARGS>
1180 promise_type(TARGS&&... args) : promise_base_type(std::forward<TARGS>(args)...) {}
1183 using promise_base_type::get_context;
1184 using promise_base_type::move_context;
1186 auto get_return_object() noexcept {
return self_type{get_context()}; }
1188 struct initial_awaitable {
1189 inline bool await_ready()
const noexcept {
return false; }
1191 inline void await_resume()
const noexcept {
1192 if (handle.promise().get_status() == task_status_type::kCreated) {
1193 task_status_type excepted = task_status_type::kCreated;
1194 handle.promise().set_status(task_status_type::kRunning, &excepted);
1200 caller.promise().initialize_promise(caller);
1205 initial_awaitable initial_suspend() noexcept {
return {}; }
1208 struct LIBCOPP_COTASK_API_HEAD_ONLY final_awaitable
1209 :
public LIBCOPP_COPP_NAMESPACE_ID::promise_base_type::final_awaitable {
1210 # if defined(LIBCOPP_MACRO_ENABLE_CONCEPTS) && LIBCOPP_MACRO_ENABLE_CONCEPTS
1211 template <std::derived_from<promise_base_type> TPROMISE>
1213 template <class TPROMISE, typename = std::enable_if_t<std::is_base_of<promise_base_type, TPROMISE>::value>>
1217 context_pointer_type context =
self.promise().move_context();
1219 # if defined(LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER) && LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER
1220 context->unbind_from_manager();
1224 LIBCOPP_COPP_NAMESPACE_ID::promise_base_type::final_awaitable::template await_suspend(
self);
1230 final_awaitable final_suspend() noexcept {
return {}; }
1232 # if defined(LIBCOPP_MACRO_ENABLE_EXCEPTION) && LIBCOPP_MACRO_ENABLE_EXCEPTION
1233 void unhandled_exception() {
1237 # elif defined(LIBCOPP_MACRO_HAS_EXCEPTION) && LIBCOPP_MACRO_HAS_EXCEPTION
1238 void unhandled_exception() {
throw; }
1240 void unhandled_exception() { std::abort(); }
1243 template <
class TCONVERT_PRIVATE_DATA>
1244 inline task_private_data<TCONVERT_PRIVATE_DATA> yield_value(
1245 task_private_data<TCONVERT_PRIVATE_DATA>&& input) noexcept {
1246 if (get_context()) {
1247 input.data_ = &get_context()->get_private_data();
1249 input.data_ =
nullptr;
1251 return task_private_data<TCONVERT_PRIVATE_DATA>(input.data_);
1254 inline task_pick_id<id_type> yield_value(task_pick_id<id_type>&& input) noexcept {
1255 if (get_context()) {
1256 input.data_ = get_context()->get_id();
1260 return task_pick_id<id_type>(input.data_);
1263 using promise_base_type::yield_value;
1266 using awaitable_type = task_awaitable<context_type, std::is_void<typename std::decay<value_type>::type>::value>;
1268 # if defined(LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER) && LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER
1269 using task_manager_helper =
typename context_type::task_manager_helper;
1273 task_future() noexcept =
default;
1274 task_future(context_pointer_type context) noexcept : base_type{context} {}
1275 task_future(
const task_future& other) noexcept : base_type{other} {}
1276 task_future(task_future&& other) noexcept : base_type{std::move(other)} {}
1277 task_future& operator=(
const task_future& other) noexcept {
1282 task_future& operator=(task_future&& other) noexcept {
1283 assign(std::move(other));
1288 using base_type::get_context;
1290 inline awaitable_type
operator co_await() {
return awaitable_type{get_context().get()}; }
1293 template <
class TTHENABLE_VALUE>
1294 struct _thenable_return_traits_value_type;
1296 template <
class TCALLABLE_VALUE,
class TTASK_ERROR_TRANSFORM>
1297 struct _thenable_return_traits_value_type<
1298 LIBCOPP_COPP_NAMESPACE_ID::callable_future<TCALLABLE_VALUE, TTASK_ERROR_TRANSFORM>> :
public std::true_type {
1301 using error_transform = TTASK_ERROR_TRANSFORM;
1303 template <
class TINPUT>
1304 UTIL_FORCEINLINE static LIBCOPP_COPP_NAMESPACE_ID::callable_future<TCALLABLE_VALUE, TTASK_ERROR_TRANSFORM>
1305 start_thenable(TINPUT&& c) {
1306 return {std::forward<TINPUT>(c)};
1310 template <
class TTASK_VALUE,
class TTASK_PRIVATE_DATA,
class TTASK_ERROR_TRANSFORM>
1311 struct _thenable_return_traits_value_type<task_future<TTASK_VALUE, TTASK_PRIVATE_DATA, TTASK_ERROR_TRANSFORM>>
1312 :
public std::true_type {
1314 using error_transform = TTASK_ERROR_TRANSFORM;
1316 template <
class TINPUT>
1317 UTIL_FORCEINLINE static task_future<TTASK_VALUE, TTASK_PRIVATE_DATA, TTASK_ERROR_TRANSFORM> start_thenable(
1320 return {std::forward<TINPUT>(
task)};
1324 template <
class TTHENABLE_VALUE>
1325 struct _thenable_return_traits_value_type :
public std::false_type {
1326 using type = TTHENABLE_VALUE;
1329 template <
class TTHENABLE,
bool TASK_RETURN_VOID>
1330 struct _thenable_return_traits_return_type;
1332 template <
class TTHENABLE>
1333 struct _thenable_return_traits_return_type<TTHENABLE, true>
1334 :
public _thenable_return_traits_value_type<typename std::invoke_result<TTHENABLE, context_pointer_type>::type> {
1337 template <
class TTHENABLE>
1338 struct _thenable_return_traits_return_type<TTHENABLE, false>
1339 :
public _thenable_return_traits_value_type<
1340 typename std::invoke_result<TTHENABLE, context_pointer_type, value_type>::type> {};
1342 template <
class TTHENABLE>
1343 struct thenable_return_traits
1344 :
public _thenable_return_traits_return_type<TTHENABLE, std::is_void<value_type>::value> {};
1346 template <
class TTHENABLE,
bool THENABLE_RETURN_COROUTINE>
1347 struct _thenable_default_error_transform;
1349 template <
class TTHENABLE>
1350 struct _thenable_default_error_transform<TTHENABLE, true> {
1351 using type =
typename thenable_return_traits<TTHENABLE>::error_transform;
1354 template <
class TTHENABLE>
1355 struct _thenable_default_error_transform<TTHENABLE, false> {
1356 using type = LIBCOPP_COPP_NAMESPACE_ID::promise_error_transform<typename thenable_return_traits<TTHENABLE>::type>;
1359 template <
class TTHENABLE>
1360 struct thenable_error_transform_traits
1361 :
public _thenable_default_error_transform<TTHENABLE, thenable_return_traits<TTHENABLE>::value> {};
1363 template <
class TTHENABLE,
class TTHENABLE_ERROR_TRANSFORM,
bool THENABLE_RETURN_COROUTINE,
bool THENABLE_RETURN_VOID,
1364 bool TASK_RETURN_VOID>
1365 struct thenable_traits;
1367 template <
class TTHENABLE,
class TTHENABLE_ERROR_TRANSFORM>
1368 struct thenable_traits<TTHENABLE, TTHENABLE_ERROR_TRANSFORM, true, false, false> {
1369 using callable_thenable_type =
1370 LIBCOPP_COPP_NAMESPACE_ID::callable_future<typename thenable_return_traits<TTHENABLE>::type,
1371 TTHENABLE_ERROR_TRANSFORM>;
1373 template <
class TTHENABLE_PRIVATE_DATA>
1374 struct task_thenable_type {
1375 using task_type = task_future<typename thenable_return_traits<TTHENABLE>::type, TTHENABLE_PRIVATE_DATA,
1376 TTHENABLE_ERROR_TRANSFORM>;
1379 inline static callable_thenable_type invoke_callable(self_type
self, TTHENABLE thenable) {
1380 co_return (co_await thenable_return_traits<TTHENABLE>::start_thenable(
1381 thenable(context_pointer_type(
self.get_context()), co_await
self)));
1384 template <
class TTHENABLE_PRIVATE_DATA>
1385 inline static typename task_thenable_type<TTHENABLE_PRIVATE_DATA>::task_type invoke_task(self_type
self,
1386 TTHENABLE thenable) {
1387 co_return (co_await thenable_return_traits<TTHENABLE>::start_thenable(
1388 thenable(context_pointer_type(
self.get_context()), co_await
self)));
1392 template <
class TTHENABLE,
class TTHENABLE_ERROR_TRANSFORM>
1393 struct thenable_traits<TTHENABLE, TTHENABLE_ERROR_TRANSFORM, true, false, true> {
1394 using callable_thenable_type =
1395 LIBCOPP_COPP_NAMESPACE_ID::callable_future<typename thenable_return_traits<TTHENABLE>::type,
1396 TTHENABLE_ERROR_TRANSFORM>;
1398 template <
class TTHENABLE_PRIVATE_DATA>
1399 struct task_thenable_type {
1400 using task_type = task_future<typename thenable_return_traits<TTHENABLE>::type, TTHENABLE_PRIVATE_DATA,
1401 TTHENABLE_ERROR_TRANSFORM>;
1404 inline static callable_thenable_type invoke_callable(self_type
self, TTHENABLE thenable) {
1406 co_return (co_await thenable_return_traits<TTHENABLE>::start_thenable(
1407 thenable(context_pointer_type(
self.get_context()))));
1410 template <
class TTHENABLE_PRIVATE_DATA>
1411 inline static typename task_thenable_type<TTHENABLE_PRIVATE_DATA>::task_type invoke_task(self_type
self,
1412 TTHENABLE thenable) {
1414 co_return (co_await thenable_return_traits<TTHENABLE>::start_thenable(
1415 thenable(context_pointer_type(
self.get_context()))));
1419 template <
class TTHENABLE,
class TTHENABLE_ERROR_TRANSFORM>
1420 struct thenable_traits<TTHENABLE, TTHENABLE_ERROR_TRANSFORM, true, true, false> {
1421 using callable_thenable_type =
1422 LIBCOPP_COPP_NAMESPACE_ID::callable_future<typename thenable_return_traits<TTHENABLE>::type,
1423 TTHENABLE_ERROR_TRANSFORM>;
1425 template <
class TTHENABLE_PRIVATE_DATA>
1426 struct task_thenable_type {
1427 using task_type = task_future<typename thenable_return_traits<TTHENABLE>::type, TTHENABLE_PRIVATE_DATA,
1428 TTHENABLE_ERROR_TRANSFORM>;
1431 inline static callable_thenable_type invoke_callable(self_type
self, TTHENABLE thenable) {
1432 co_await thenable_return_traits<TTHENABLE>::start_thenable(
1433 thenable(context_pointer_type(
self.get_context()), co_await
self));
1437 template <
class TTHENABLE_PRIVATE_DATA>
1438 inline static typename task_thenable_type<TTHENABLE_PRIVATE_DATA>::task_type invoke_task(self_type
self,
1439 TTHENABLE thenable) {
1440 co_await thenable_return_traits<TTHENABLE>::start_thenable(
1441 thenable(context_pointer_type(
self.get_context()), co_await
self));
1446 template <
class TTHENABLE,
class TTHENABLE_ERROR_TRANSFORM>
1447 struct thenable_traits<TTHENABLE, TTHENABLE_ERROR_TRANSFORM, true, true, true> {
1448 using callable_thenable_type =
1449 LIBCOPP_COPP_NAMESPACE_ID::callable_future<typename thenable_return_traits<TTHENABLE>::type,
1450 TTHENABLE_ERROR_TRANSFORM>;
1452 template <
class TTHENABLE_PRIVATE_DATA>
1453 struct task_thenable_type {
1454 using task_type = task_future<typename thenable_return_traits<TTHENABLE>::type, TTHENABLE_PRIVATE_DATA,
1455 TTHENABLE_ERROR_TRANSFORM>;
1458 inline static callable_thenable_type invoke_callable(self_type
self, TTHENABLE thenable) {
1460 co_await thenable_return_traits<TTHENABLE>::start_thenable(thenable(context_pointer_type(
self.get_context())));
1464 template <
class TTHENABLE_PRIVATE_DATA>
1465 inline static typename task_thenable_type<TTHENABLE_PRIVATE_DATA>::task_type invoke_task(self_type
self,
1466 TTHENABLE thenable) {
1468 co_await thenable_return_traits<TTHENABLE>::start_thenable(thenable(context_pointer_type(
self.get_context())));
1473 template <
class TTHENABLE,
class TTHENABLE_ERROR_TRANSFORM>
1474 struct thenable_traits<TTHENABLE, TTHENABLE_ERROR_TRANSFORM, false, true, false> {
1475 using callable_thenable_type =
1476 LIBCOPP_COPP_NAMESPACE_ID::callable_future<typename thenable_return_traits<TTHENABLE>::type,
1477 TTHENABLE_ERROR_TRANSFORM>;
1479 template <
class TTHENABLE_PRIVATE_DATA>
1480 struct task_thenable_type {
1481 using task_type = task_future<typename thenable_return_traits<TTHENABLE>::type, TTHENABLE_PRIVATE_DATA,
1482 TTHENABLE_ERROR_TRANSFORM>;
1485 inline static callable_thenable_type invoke_callable(self_type
self, TTHENABLE thenable) {
1486 thenable(context_pointer_type(
self.get_context()), co_await
self);
1490 template <
class TTHENABLE_PRIVATE_DATA>
1491 inline static typename task_thenable_type<TTHENABLE_PRIVATE_DATA>::task_type invoke_task(self_type
self,
1492 TTHENABLE thenable) {
1493 thenable(context_pointer_type(
self.get_context()), co_await
self);
1498 template <
class TTHENABLE,
class TTHENABLE_ERROR_TRANSFORM>
1499 struct thenable_traits<TTHENABLE, TTHENABLE_ERROR_TRANSFORM, false, true, true> {
1500 using callable_thenable_type =
1501 LIBCOPP_COPP_NAMESPACE_ID::callable_future<typename thenable_return_traits<TTHENABLE>::type,
1502 TTHENABLE_ERROR_TRANSFORM>;
1504 template <
class TTHENABLE_PRIVATE_DATA>
1505 struct task_thenable_type {
1506 using task_type = task_future<typename thenable_return_traits<TTHENABLE>::type, TTHENABLE_PRIVATE_DATA,
1507 TTHENABLE_ERROR_TRANSFORM>;
1510 inline static callable_thenable_type invoke_callable(self_type
self, TTHENABLE thenable) {
1512 thenable(context_pointer_type(
self.get_context()));
1516 template <
class TTHENABLE_PRIVATE_DATA>
1517 inline static typename task_thenable_type<TTHENABLE_PRIVATE_DATA>::task_type invoke_task(self_type
self,
1518 TTHENABLE thenable) {
1520 thenable(context_pointer_type(
self.get_context()));
1525 template <
class TTHENABLE,
class TTHENABLE_ERROR_TRANSFORM>
1526 struct thenable_traits<TTHENABLE, TTHENABLE_ERROR_TRANSFORM, false, false, false> {
1527 using callable_thenable_type =
1528 LIBCOPP_COPP_NAMESPACE_ID::callable_future<typename thenable_return_traits<TTHENABLE>::type,
1529 TTHENABLE_ERROR_TRANSFORM>;
1531 template <
class TTHENABLE_PRIVATE_DATA>
1532 struct task_thenable_type {
1533 using task_type = task_future<typename thenable_return_traits<TTHENABLE>::type, TTHENABLE_PRIVATE_DATA,
1534 TTHENABLE_ERROR_TRANSFORM>;
1537 inline static callable_thenable_type invoke_callable(self_type
self, TTHENABLE thenable) {
1538 co_return thenable(context_pointer_type(
self.get_context()), co_await
self);
1541 template <
class TTHENABLE_PRIVATE_DATA>
1542 inline static typename task_thenable_type<TTHENABLE_PRIVATE_DATA>::task_type invoke_task(self_type
self,
1543 TTHENABLE thenable) {
1544 co_return thenable(context_pointer_type(
self.get_context()), co_await
self);
1548 template <
class TTHENABLE,
class TTHENABLE_ERROR_TRANSFORM>
1549 struct thenable_traits<TTHENABLE, TTHENABLE_ERROR_TRANSFORM, false, false, true> {
1550 using callable_thenable_type =
1551 LIBCOPP_COPP_NAMESPACE_ID::callable_future<typename thenable_return_traits<TTHENABLE>::type,
1552 TTHENABLE_ERROR_TRANSFORM>;
1554 template <
class TTHENABLE_PRIVATE_DATA>
1555 struct task_thenable_type {
1556 using task_type = task_future<typename thenable_return_traits<TTHENABLE>::type, TTHENABLE_PRIVATE_DATA,
1557 TTHENABLE_ERROR_TRANSFORM>;
1560 inline static callable_thenable_type invoke_callable(self_type
self, TTHENABLE thenable) {
1562 co_return thenable(context_pointer_type(
self.get_context()));
1565 template <
class TTHENABLE_PRIVATE_DATA>
1566 inline static typename task_thenable_type<TTHENABLE_PRIVATE_DATA>::task_type invoke_task(self_type
self,
1567 TTHENABLE thenable) {
1569 co_return thenable(context_pointer_type(
self.get_context()));
1574 template <
class TTHENABLE,
class TTHENABLE_ERROR_TRANSFORM>
1575 struct callable_thenable_trait {
1576 using trait_type = thenable_traits<
1577 typename std::decay<TTHENABLE>::type, TTHENABLE_ERROR_TRANSFORM,
1578 thenable_return_traits<typename std::decay<TTHENABLE>::type>::value,
1579 std::is_same<typename thenable_return_traits<typename std::decay<TTHENABLE>::type>::type,
void>::value,
1580 std::is_void<value_type>::value>;
1582 using callable_thenable_type =
typename trait_type::callable_thenable_type;
1585 template <
class TTHENABLE,
class TTHENABLE_PRIVATE_DATA,
class TTHENABLE_ERROR_TRANSFORM>
1586 struct task_thenable_trait {
1587 using trait_type = thenable_traits<
1588 typename std::decay<TTHENABLE>::type, TTHENABLE_ERROR_TRANSFORM,
1589 thenable_return_traits<typename std::decay<TTHENABLE>::type>::value,
1590 std::is_same<typename thenable_return_traits<typename std::decay<TTHENABLE>::type>::type,
void>::value,
1591 std::is_void<value_type>::value>;
1593 using task_thenable_wrapper =
typename trait_type::template task_thenable_type<TTHENABLE_PRIVATE_DATA>;
1594 using task_thenable_type =
typename task_thenable_wrapper::task_type;
1618 template <
class TTHENABLE,
1619 class TTHENABLE_ERROR_TRANSFORM =
typename thenable_error_transform_traits<TTHENABLE>::type>
1620 typename callable_thenable_trait<TTHENABLE, TTHENABLE_ERROR_TRANSFORM>::callable_thenable_type then(
1621 TTHENABLE&& thenable) {
1622 using trait_type =
typename callable_thenable_trait<TTHENABLE, TTHENABLE_ERROR_TRANSFORM>::trait_type;
1623 return trait_type::invoke_callable(*
this, std::forward<TTHENABLE>(thenable));
1652 template <
class TTHENABLE,
class TTHENABLE_PRIVATE_DATA,
1653 class TTHENABLE_ERROR_TRANSFORM =
typename thenable_error_transform_traits<TTHENABLE>::type>
1654 typename task_thenable_trait<TTHENABLE, typename std::decay<TTHENABLE_PRIVATE_DATA>::type,
1655 TTHENABLE_ERROR_TRANSFORM>::task_thenable_type
1656 then(TTHENABLE&& thenable, TTHENABLE_PRIVATE_DATA&& private_data) {
1657 using trait_type =
typename task_thenable_trait<TTHENABLE, typename std::decay<TTHENABLE_PRIVATE_DATA>::type,
1658 TTHENABLE_ERROR_TRANSFORM>::trait_type;
1659 auto result = trait_type::template invoke_task<typename std::decay<TTHENABLE_PRIVATE_DATA>::type>(
1660 *
this, std::forward<TTHENABLE>(thenable));
1661 *result.get_private_data() = std::forward<TTHENABLE_PRIVATE_DATA>(private_data);
1692 template <
class TTHENABLE,
1693 class TTHENABLE_ERROR_TRANSFORM =
typename thenable_error_transform_traits<TTHENABLE>::type>
1694 typename task_thenable_trait<TTHENABLE, void, TTHENABLE_ERROR_TRANSFORM>::task_thenable_type then(
1695 TTHENABLE&& thenable, std::nullptr_t) {
1696 using trait_type =
typename task_thenable_trait<TTHENABLE, void, TTHENABLE_ERROR_TRANSFORM>::trait_type;
1697 auto result = trait_type::template invoke_task<void>(*
this, std::forward<TTHENABLE>(thenable));
1704 template <
class TVALUE,
class TPRIVATE_DATA,
class TERROR_TRANSFORM>
1705 struct LIBCOPP_COTASK_API_HEAD_ONLY some_delegate_task_action {
1706 using future_type = task_future<TVALUE, TPRIVATE_DATA, TERROR_TRANSFORM>;
1707 using context_type = LIBCOPP_COPP_NAMESPACE_ID::some_delegate_context<future_type>;
1709 inline static void suspend_future(
const LIBCOPP_COPP_NAMESPACE_ID::promise_caller_manager::handle_delegate& caller,
1710 future_type& task_object) {
1711 if (task_object.get_context()) {
1712 task_object.get_context()->add_caller(caller);
1716 inline static void resume_future(
const LIBCOPP_COPP_NAMESPACE_ID::promise_caller_manager::handle_delegate& caller,
1717 future_type& task_object) {
1718 if (task_object.get_context()) {
1719 task_object.get_context()->remove_caller(caller);
1723 inline static bool is_pending(future_type& future_object) noexcept {
return !future_object.is_exiting(); }
1726 LIBCOPP_COTASK_NAMESPACE_END
1728 LIBCOPP_COPP_NAMESPACE_BEGIN
1730 template <
class TVALUE,
class TPRIVATE_DATA,
class TERROR_TRANSFORM>
1731 class LIBCOPP_COTASK_API_HEAD_ONLY some_delegate<cotask::task_future<TVALUE, TPRIVATE_DATA, TERROR_TRANSFORM>>
1732 :
public some_delegate_base<cotask::task_future<TVALUE, TPRIVATE_DATA, TERROR_TRANSFORM>,
1733 cotask::some_delegate_task_action<TVALUE, TPRIVATE_DATA, TERROR_TRANSFORM>> {
1735 using base_type = some_delegate_base<cotask::task_future<TVALUE, TPRIVATE_DATA, TERROR_TRANSFORM>,
1736 cotask::some_delegate_task_action<TVALUE, TPRIVATE_DATA, TERROR_TRANSFORM>>;
1737 using future_type =
typename base_type::future_type;
1739 using ready_output_type =
typename base_type::ready_output_type;
1740 using context_type =
typename base_type::context_type;
1742 using base_type::run;
1745 LIBCOPP_COPP_NAMESPACE_END
int start(void *priv_data, EN_TASK_STATUS expected_status=EN_TS_CREATED) override
#define LIBCOPP_MACRO_STD_COROUTINE_NAMESPACE
#define COPP_UNLIKELY_IF(...)
#define COPP_LIKELY_IF(...)
锁管理器 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())
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