5#include <libcopp/utils/config/libcopp_build_features.h>
20#include <unordered_map>
23#ifdef __cpp_impl_three_way_comparison
27#if defined(LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR) && LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR
37LIBCOPP_COTASK_NAMESPACE_BEGIN
48#ifdef __cpp_impl_three_way_comparison
75template <
class TTASK_ID_TYPE>
84#ifdef __cpp_impl_three_way_comparison
131template <
class TTask>
134template <
class TCO_MACRO>
142 LIBCOPP_COPP_NAMESPACE_ID::util::iterator_guard<task_timer_container_type>
timer_node;
145#if defined(LIBCOPP_MACRO_ENABLE_STD_COROUTINE) && LIBCOPP_MACRO_ENABLE_STD_COROUTINE
146template <
class TVALUE,
class TPRIVATE_DATA,
class TERROR_TRANSFORM>
147struct LIBCOPP_COTASK_API_HEAD_ONLY
task_manager_node<task_future<TVALUE, TPRIVATE_DATA, TERROR_TRANSFORM>> {
148 using task_type = task_future<TVALUE, TPRIVATE_DATA, TERROR_TRANSFORM>;
149 using task_id_type =
typename task_type::id_type;
151 using task_timer_container_type = std::set<task_timer_node_type>;
154 LIBCOPP_COPP_NAMESPACE_ID::util::iterator_guard<task_timer_container_type> timer_node;
160template <
typename TTask>
166template <
typename TCO_MACRO>
170 using container_type = std::unordered_map<typename task_type::id_type, detail::task_manager_node<task_type>>;
174 using ptr_type = LIBCOPP_COPP_NAMESPACE_ID::memory::default_strong_rc_ptr<self_type>;
179 EN_TM_IN_TICK = 0x01,
180 EN_TM_IN_RESET = 0x02,
176 struct flag_type {
…};
194 struct flag_guard_type {
198 if (
nullptr == data_ || (*data_ & flag_)) {
199 flag_ = flag_type::EN_TM_NONE;
211 inline operator bool() {
return nullptr != data_ && flag_type::EN_TM_NONE != flag_; }
194 struct flag_guard_type {
…};
216 last_tick_time_.tv_sec = 0;
217 last_tick_time_.tv_nsec = 0;
226 flag_guard_type reset_flag(&flags_, flag_type::EN_TM_IN_RESET);
231 std::vector<task_ptr_type> all_tasks;
234#if LIBCOPP_MACRO_ENABLE_MULTI_THREAD
235 LIBCOPP_COPP_NAMESPACE_ID::util::lock::lock_holder<LIBCOPP_COPP_NAMESPACE_ID::util::lock::spin_lock> lock_guard{
239 for (
typename container_type::iterator iter = tasks_.begin(); iter != tasks_.end(); ++iter) {
240 all_tasks.push_back(iter->second.task_);
241 remove_timeout_timer(iter->second);
245 task_timeout_timer_.clear();
247 last_tick_time_.tv_sec = 0;
248 last_tick_time_.tv_nsec = 0;
252 for (
typename std::vector<task_ptr_type>::iterator iter = all_tasks.begin(); iter != all_tasks.end(); ++iter) {
253 if (!(*iter)->is_exiting()) {
263 static ptr_type create() {
return LIBCOPP_COPP_NAMESPACE_ID::memory::default_make_strong<self_type>(); }
281 return LIBCOPP_COPP_NAMESPACE_ID::COPP_EC_ARGS_ERROR;
284 if (flags_ & flag_type::EN_TM_IN_RESET) {
285 return LIBCOPP_COPP_NAMESPACE_ID::COPP_EC_IN_RESET;
289 return LIBCOPP_COPP_NAMESPACE_ID::COPP_EC_TASK_IS_EXITING;
293 using pair_type =
typename container_type::value_type;
294 detail::task_manager_node<task_type> task_node;
295 task_node.task_ =
task;
296 task_node.timer_node.reset(task_timeout_timer_);
298 if (!task_node.task_) {
299 assert(task_node.task_);
300 return LIBCOPP_COPP_NAMESPACE_ID::COPP_EC_CAST_FAILED;
304#if LIBCOPP_MACRO_ENABLE_MULTI_THREAD
305 LIBCOPP_COPP_NAMESPACE_ID::util::lock::lock_holder<LIBCOPP_COPP_NAMESPACE_ID::util::lock::spin_lock> lock_guard{
310 if (tasks_.end() != tasks_.find(task_id)) {
311 return LIBCOPP_COPP_NAMESPACE_ID::COPP_EC_ALREADY_EXIST;
314#if defined(LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER) && LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER
315 using task_manager_helper =
typename task_type::task_manager_helper;
316 if (!task_manager_helper::setup_task_manager(*
task,
reinterpret_cast<void *
>(
this), &task_cleanup_callback)) {
317 return LIBCOPP_COPP_NAMESPACE_ID::COPP_EC_TASK_ALREADY_IN_ANOTHER_MANAGER;
322 std::pair<typename container_type::iterator, bool> res = tasks_.insert(pair_type(task_id, task_node));
323 if (
false == res.second) {
324#if defined(LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER) && LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER
325 task_manager_helper::cleanup_task_manager(*
task,
reinterpret_cast<void *
>(
this));
327 return LIBCOPP_COPP_NAMESPACE_ID::COPP_EC_EXTERNAL_INSERT_FAILED;
331 set_timeout_timer(res.first->second, timeout_sec, timeout_nsec);
332 return LIBCOPP_COPP_NAMESPACE_ID::COPP_EC_SUCCESS;
360 if (flags_ & flag_type::EN_TM_IN_RESET) {
361 return LIBCOPP_COPP_NAMESPACE_ID::COPP_EC_IN_RESET;
365#if LIBCOPP_MACRO_ENABLE_MULTI_THREAD
366 LIBCOPP_COPP_NAMESPACE_ID::util::lock::lock_holder<LIBCOPP_COPP_NAMESPACE_ID::util::lock::spin_lock> lock_guard{
370 using iter_type =
typename container_type::iterator;
371 iter_type iter = tasks_.find(
id);
372 if (tasks_.end() == iter)
return LIBCOPP_COPP_NAMESPACE_ID::COPP_EC_NOT_FOUND;
374 set_timeout_timer(iter->second, timeout_sec, timeout_nsec);
377 return LIBCOPP_COPP_NAMESPACE_ID::COPP_EC_SUCCESS;
402 if (flags_ & flag_type::EN_TM_IN_RESET) {
403 return LIBCOPP_COPP_NAMESPACE_ID::COPP_EC_IN_RESET;
408#if LIBCOPP_MACRO_ENABLE_MULTI_THREAD
409 LIBCOPP_COPP_NAMESPACE_ID::util::lock::lock_holder<LIBCOPP_COPP_NAMESPACE_ID::util::lock::spin_lock> lock_guard{
413 using iter_type =
typename container_type::iterator;
414 iter_type iter = tasks_.find(
id);
415 if (tasks_.end() == iter) {
416 return LIBCOPP_COPP_NAMESPACE_ID::COPP_EC_NOT_FOUND;
418 if (
nullptr != confirm_ptr && iter->second.task_.get() != confirm_ptr) {
419 return LIBCOPP_COPP_NAMESPACE_ID::COPP_EC_NOT_FOUND;
423 task_inst = std::move(iter->second.task_);
425 remove_timeout_timer(iter->second);
430#if defined(LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER) && LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER
431 using task_manager_helper =
typename task_type::task_manager_helper;
433 task_manager_helper::cleanup_task_manager(*task_inst,
reinterpret_cast<void *
>(
this));
442 return LIBCOPP_COPP_NAMESPACE_ID::COPP_EC_SUCCESS;
451 if (flags_ & flag_type::EN_TM_IN_RESET) {
455#if LIBCOPP_MACRO_ENABLE_MULTI_THREAD
456 LIBCOPP_COPP_NAMESPACE_ID::util::lock::lock_holder<LIBCOPP_COPP_NAMESPACE_ID::util::lock::spin_lock> lock_guard{
460 using iter_type =
typename container_type::iterator;
461 iter_type iter = tasks_.find(
id);
464 return iter->second.task_;
470#if defined(LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR) && LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR
471 int start(id_type
id,
void *priv_data =
nullptr) {
472 std::list<std::exception_ptr> eptrs;
473 int ret = start(
id, eptrs, priv_data);
474 task_type::maybe_rethrow(eptrs);
478 int start(id_type
id, std::list<std::exception_ptr> &unhandled,
void *priv_data =
nullptr) LIBCOPP_MACRO_NOEXCEPT {
482 if (flags_ & flag_type::EN_TM_IN_RESET) {
483 return LIBCOPP_COPP_NAMESPACE_ID::COPP_EC_IN_RESET;
488#if LIBCOPP_MACRO_ENABLE_MULTI_THREAD
489 LIBCOPP_COPP_NAMESPACE_ID::util::lock::lock_holder<LIBCOPP_COPP_NAMESPACE_ID::util::lock::spin_lock> lock_guard{
493 using iter_type =
typename container_type::iterator;
494 iter_type iter = tasks_.find(
id);
495 if (tasks_.end() == iter)
return LIBCOPP_COPP_NAMESPACE_ID::COPP_EC_NOT_FOUND;
497 task_inst = iter->second.task_;
502#if defined(LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR) && LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR
503 int ret = task_inst->start(unhandled, priv_data);
505 int ret = task_inst->start(priv_data);
515 return LIBCOPP_COPP_NAMESPACE_ID::COPP_EC_NOT_FOUND;
519#if defined(LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR) && LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR
520 int resume(id_type
id,
void *priv_data =
nullptr) {
521 std::list<std::exception_ptr> eptrs;
522 int ret = resume(
id, eptrs, priv_data);
523 task_type::maybe_rethrow(eptrs);
527 int resume(id_type
id, std::list<std::exception_ptr> &unhandled,
void *priv_data =
nullptr) LIBCOPP_MACRO_NOEXCEPT {
531 if (flags_ & flag_type::EN_TM_IN_RESET) {
532 return LIBCOPP_COPP_NAMESPACE_ID::COPP_EC_IN_RESET;
537#if LIBCOPP_MACRO_ENABLE_MULTI_THREAD
538 LIBCOPP_COPP_NAMESPACE_ID::util::lock::lock_holder<LIBCOPP_COPP_NAMESPACE_ID::util::lock::spin_lock> lock_guard{
542 using iter_type =
typename container_type::iterator;
543 iter_type iter = tasks_.find(
id);
544 if (tasks_.end() == iter)
return LIBCOPP_COPP_NAMESPACE_ID::COPP_EC_NOT_FOUND;
546 task_inst = iter->second.task_;
551#if defined(LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR) && LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR
552 int ret = task_inst->resume(unhandled, priv_data);
554 int ret = task_inst->resume(priv_data);
564 return LIBCOPP_COPP_NAMESPACE_ID::COPP_EC_NOT_FOUND;
568#if defined(LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR) && LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR
569 int cancel(id_type
id,
void *priv_data =
nullptr) {
570 std::list<std::exception_ptr> eptrs;
571 int ret = cancel(
id, eptrs, priv_data);
572 task_type::maybe_rethrow(eptrs);
576 int cancel(id_type
id, std::list<std::exception_ptr> &unhandled,
void *priv_data =
nullptr) LIBCOPP_MACRO_NOEXCEPT {
580 if (flags_ & flag_type::EN_TM_IN_RESET) {
581 return LIBCOPP_COPP_NAMESPACE_ID::COPP_EC_IN_RESET;
586#if LIBCOPP_MACRO_ENABLE_MULTI_THREAD
587 LIBCOPP_COPP_NAMESPACE_ID::util::lock::lock_holder<LIBCOPP_COPP_NAMESPACE_ID::util::lock::spin_lock> lock_guard{
591 using iter_type =
typename container_type::iterator;
592 iter_type iter = tasks_.find(
id);
593 if (tasks_.end() == iter) {
594 return LIBCOPP_COPP_NAMESPACE_ID::COPP_EC_NOT_FOUND;
597 task_inst = std::move(iter->second.task_);
599 remove_timeout_timer(iter->second);
605#if defined(LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER) && LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER
606 using task_manager_helper =
typename task_type::task_manager_helper;
608 task_manager_helper::cleanup_task_manager(*task_inst,
reinterpret_cast<void *
>(
this));
610#if defined(LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR) && LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR
611 return task_inst->cancel(unhandled, priv_data);
613 return task_inst->cancel(priv_data);
616 return LIBCOPP_COPP_NAMESPACE_ID::COPP_EC_NOT_FOUND;
620#if defined(LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR) && LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR
621 int kill(id_type
id,
enum EN_TASK_STATUS status,
void *priv_data =
nullptr) {
622 std::list<std::exception_ptr> eptrs;
623 int ret = kill(
id, eptrs, status, priv_data);
624 task_type::maybe_rethrow(eptrs);
628 int kill(id_type
id, std::list<std::exception_ptr> &unhandled,
enum EN_TASK_STATUS status,
629 void *priv_data =
nullptr) LIBCOPP_MACRO_NOEXCEPT {
633 if (flags_ & flag_type::EN_TM_IN_RESET) {
634 return LIBCOPP_COPP_NAMESPACE_ID::COPP_EC_IN_RESET;
639#if LIBCOPP_MACRO_ENABLE_MULTI_THREAD
640 LIBCOPP_COPP_NAMESPACE_ID::util::lock::lock_holder<LIBCOPP_COPP_NAMESPACE_ID::util::lock::spin_lock> lock_guard{
644 using iter_type =
typename container_type::iterator;
645 iter_type iter = tasks_.find(
id);
646 if (tasks_.end() == iter) {
647 return LIBCOPP_COPP_NAMESPACE_ID::COPP_EC_NOT_FOUND;
650 task_inst = std::move(iter->second.task_);
652 remove_timeout_timer(iter->second);
658#if defined(LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER) && LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER
659 using task_manager_helper =
typename task_type::task_manager_helper;
661 task_manager_helper::cleanup_task_manager(*task_inst,
reinterpret_cast<void *
>(
this));
663#if defined(LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR) && LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR
664 return task_inst->kill(unhandled, status, priv_data);
666 return task_inst->kill(status, priv_data);
669 return LIBCOPP_COPP_NAMESPACE_ID::COPP_EC_NOT_FOUND;
683 int tick(time_t sec,
int nsec = 0) {
686 if (sec < last_tick_time_.tv_sec || (sec == last_tick_time_.tv_sec && nsec <= last_tick_time_.tv_nsec)) {
690 now_tick_time.
tv_sec = sec;
694 flag_guard_type tick_flag(&flags_, flag_type::EN_TM_IN_TICK);
696 return LIBCOPP_COPP_NAMESPACE_ID::COPP_EC_SUCCESS;
699 if (flags_ & flag_type::EN_TM_IN_RESET) {
700 return LIBCOPP_COPP_NAMESPACE_ID::COPP_EC_IN_RESET;
704 if (0 == last_tick_time_.tv_sec && 0 == last_tick_time_.tv_nsec) {
706#if LIBCOPP_MACRO_ENABLE_MULTI_THREAD
707 LIBCOPP_COPP_NAMESPACE_ID::util::lock::lock_holder<LIBCOPP_COPP_NAMESPACE_ID::util::lock::spin_lock> lock_guard{
711 std::set<detail::task_timer_node<id_type>> real_checkpoints;
713 task_timeout_timer_.end() != iter; ++iter) {
717 real_checkpoints.insert(new_checkpoint);
720 task_timeout_timer_.swap(real_checkpoints);
722 task_timeout_timer_.end() != iter; ++iter) {
723 const typename std::set<detail::task_timer_node<id_type>>::value_type &checkpoint = *iter;
724 using co_iter_type =
typename container_type::iterator;
725 co_iter_type co_iter = tasks_.find(checkpoint.task_id);
727 if (tasks_.end() != co_iter) {
728 co_iter->second.timer_node.set(task_timeout_timer_, iter);
731 last_tick_time_ = now_tick_time;
732 return LIBCOPP_COPP_NAMESPACE_ID::COPP_EC_SUCCESS;
735#if defined(LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR) && LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR
736 std::list<std::exception_ptr> eptrs;
739 while (
false == task_timeout_timer_.empty()) {
744#if LIBCOPP_MACRO_ENABLE_MULTI_THREAD
745 LIBCOPP_COPP_NAMESPACE_ID::util::lock::lock_holder<LIBCOPP_COPP_NAMESPACE_ID::util::lock::spin_lock> lock_guard{
749 const typename std::set<detail::task_timer_node<id_type>>::value_type &timer_node_value =
750 *task_timeout_timer_.begin();
752 if (now_tick_time <= timer_node_value.expired_time) {
757 using iter_type =
typename container_type::iterator;
759 iter_type iter = tasks_.find(timer_node_value.task_id);
761 if (tasks_.end() != iter) {
763 task_inst = std::move(iter->second.task_);
765 remove_timeout_timer(iter->second);
771 if (task_inst && !task_inst->is_exiting()) {
772#if defined(LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER) && LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER
773 using task_manager_helper =
typename task_type::task_manager_helper;
775 task_manager_helper::cleanup_task_manager(*task_inst,
reinterpret_cast<void *
>(
this));
777#if defined(LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR) && LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR
785 last_tick_time_ = now_tick_time;
787#if defined(LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR) && LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR
788 task_type::maybe_rethrow(eptrs);
790 return LIBCOPP_COPP_NAMESPACE_ID::COPP_EC_SUCCESS;
683 int tick(time_t sec,
int nsec = 0) {
…}
803 size_t get_task_size() const LIBCOPP_MACRO_NOEXCEPT {
return tasks_.size(); }
821 inline const std::set<detail::task_timer_node<id_type>> &
get_checkpoints() const LIBCOPP_MACRO_NOEXCEPT {
822 return task_timeout_timer_;
821 inline const std::set<detail::task_timer_node<id_type>> &
get_checkpoints() const LIBCOPP_MACRO_NOEXCEPT {
…}
826 void set_timeout_timer(detail::task_manager_node<task_type> &node, time_t timeout_sec,
int timeout_nsec) {
827 remove_timeout_timer(node);
829 if (timeout_sec <= 0 && timeout_nsec <= 0) {
838 timer_node_value.
task_id = node.task_->get_id();
842 std::pair<typename std::set<detail::task_timer_node<id_type>>::iterator,
bool> res =
843 task_timeout_timer_.insert(timer_node_value);
845 node.timer_node.set(task_timeout_timer_, res.first);
826 void set_timeout_timer(detail::task_manager_node<task_type> &node, time_t timeout_sec,
int timeout_nsec) {
…}
850 if (node.timer_node.valid(task_timeout_timer_)) {
851 task_timeout_timer_.erase(node.timer_node.release(task_timeout_timer_));
855#if defined(LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER) && LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER
856 static void task_cleanup_callback(
void *self_ptr, task_type &task_inst) {
857 if (
nullptr == self_ptr) {
861 reinterpret_cast<self_type *
>(self_ptr)->remove_task(task_inst.get_id(), &task_inst);
870#if LIBCOPP_MACRO_ENABLE_MULTI_THREAD
871 LIBCOPP_COPP_NAMESPACE_ID::util::lock::spin_lock action_lock_;
876#if defined(LIBCOPP_MACRO_ENABLE_STD_COROUTINE) && LIBCOPP_MACRO_ENABLE_STD_COROUTINE
880template <
class TVALUE,
class TPRIVATE_DATA,
class TERROR_TRANSFORM>
881class LIBCOPP_COTASK_API_HEAD_ONLY
task_manager<task_future<TVALUE, TPRIVATE_DATA, TERROR_TRANSFORM>> {
883 using task_type = task_future<TVALUE, TPRIVATE_DATA, TERROR_TRANSFORM>;
884 using container_type = std::unordered_map<typename task_type::id_type, detail::task_manager_node<task_type>>;
885 using id_type =
typename task_type::id_type;
886 using task_status_type =
typename task_type::task_status_type;
887 using self_type = task_manager<task_type>;
888 using ptr_type = LIBCOPP_COPP_NAMESPACE_ID::memory::default_strong_rc_ptr<self_type>;
890 enum class flag_type : uint32_t {
897 struct flag_guard_type {
900 inline flag_guard_type(uint32_t *flags, flag_type v) : data_(flags), flag_(v) {
901 if (
nullptr == data_ || (*data_ &
static_cast<uint32_t
>(flag_))) {
902 flag_ = flag_type::kNone;
905 (*data_) |=
static_cast<uint32_t
>(flag_);
908 inline ~flag_guard_type() {
910 (*data_) &= ~static_cast<uint32_t>(flag_);
914 inline operator bool() {
return nullptr != data_ && flag_type::kNone != flag_; }
919 last_tick_time_.tv_sec = 0;
920 last_tick_time_.tv_nsec = 0;
929 flag_guard_type reset_flag(&flags_, flag_type::kTimerReset);
934 std::vector<task_type> all_tasks;
937# if LIBCOPP_MACRO_ENABLE_MULTI_THREAD
938 LIBCOPP_COPP_NAMESPACE_ID::util::lock::lock_holder<LIBCOPP_COPP_NAMESPACE_ID::util::lock::spin_lock> lock_guard{
942 for (
typename container_type::iterator iter = tasks_.begin(); iter != tasks_.end(); ++iter) {
943 all_tasks.push_back(iter->second.task_);
944 remove_timeout_timer(iter->second);
948 task_timeout_timer_.clear();
950 last_tick_time_.tv_sec = 0;
951 last_tick_time_.tv_nsec = 0;
955 for (
typename std::vector<task_type>::iterator iter = all_tasks.begin(); iter != all_tasks.end(); ++iter) {
956 if (!(*iter).is_exiting()) {
957# if defined(LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER) && LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER
958 using task_manager_helper =
typename task_type::task_manager_helper;
960 task_manager_helper::cleanup_task_manager(*(*iter).get_context(),
reinterpret_cast<void *
>(
this));
963 (*iter).kill(task_status_type::kKilled);
972 static ptr_type create() noexcept {
return LIBCOPP_COPP_NAMESPACE_ID::memory::default_make_strong<self_type>(); }
987 int add_task(
const task_type &
task, time_t timeout_sec,
int timeout_nsec)
noexcept {
988 if (flags_ &
static_cast<uint32_t
>(flag_type::kTimerReset)) {
989 return LIBCOPP_COPP_NAMESPACE_ID::COPP_EC_IN_RESET;
993 return LIBCOPP_COPP_NAMESPACE_ID::COPP_EC_TASK_IS_EXITING;
997 using pair_type =
typename container_type::value_type;
998 detail::task_manager_node<task_type> task_node;
999 task_node.task_ =
task;
1000 task_node.timer_node.reset(task_timeout_timer_);
1003# if LIBCOPP_MACRO_ENABLE_MULTI_THREAD
1004 LIBCOPP_COPP_NAMESPACE_ID::util::lock::lock_holder<LIBCOPP_COPP_NAMESPACE_ID::util::lock::spin_lock> lock_guard{
1009 if (tasks_.end() != tasks_.find(task_id)) {
1010 return LIBCOPP_COPP_NAMESPACE_ID::COPP_EC_ALREADY_EXIST;
1013# if defined(LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER) && LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER
1014 using task_manager_helper =
typename task_type::task_manager_helper;
1015 if (!task_manager_helper::setup_task_manager(*
task.get_context(),
reinterpret_cast<void *
>(
this),
1016 &task_cleanup_callback)) {
1017 return LIBCOPP_COPP_NAMESPACE_ID::COPP_EC_TASK_ALREADY_IN_ANOTHER_MANAGER;
1022 std::pair<typename container_type::iterator, bool> res = tasks_.insert(pair_type(task_id, task_node));
1023 if (
false == res.second) {
1024# if defined(LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER) && LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER
1025 task_manager_helper::cleanup_task_manager(*
task.get_context(),
reinterpret_cast<void *
>(
this));
1027 return LIBCOPP_COPP_NAMESPACE_ID::COPP_EC_EXTERNAL_INSERT_FAILED;
1031 set_timeout_timer(res.first->second, timeout_sec, timeout_nsec);
1032 return LIBCOPP_COPP_NAMESPACE_ID::COPP_EC_SUCCESS;
1043 int add_task(
const task_type &
task)
noexcept {
return add_task(
task, 0, 0); }
1059 int set_timeout(id_type
id, time_t timeout_sec,
int timeout_nsec)
noexcept {
1060 if (flags_ &
static_cast<uint32_t
>(flag_type::kTimerReset)) {
1061 return LIBCOPP_COPP_NAMESPACE_ID::COPP_EC_IN_RESET;
1065# if LIBCOPP_MACRO_ENABLE_MULTI_THREAD
1066 LIBCOPP_COPP_NAMESPACE_ID::util::lock::lock_holder<LIBCOPP_COPP_NAMESPACE_ID::util::lock::spin_lock> lock_guard{
1070 using iter_type =
typename container_type::iterator;
1071 iter_type iter = tasks_.find(
id);
1072 if (tasks_.end() == iter)
return LIBCOPP_COPP_NAMESPACE_ID::COPP_EC_NOT_FOUND;
1074 set_timeout_timer(iter->second, timeout_sec, timeout_nsec);
1077 return LIBCOPP_COPP_NAMESPACE_ID::COPP_EC_SUCCESS;
1086 inline int remove_task(id_type
id,
const task_type &confirm_task) {
1087 return remove_task(
id, confirm_task.get_context().get());
1095 inline int remove_task(id_type
id) {
return remove_task(
id,
nullptr); }
1103 int remove_task(id_type
id,
const task_context_base<TVALUE> *confirm_context) {
1104 if (flags_ &
static_cast<uint32_t
>(flag_type::kTimerReset)) {
1105 return LIBCOPP_COPP_NAMESPACE_ID::COPP_EC_IN_RESET;
1108 task_type task_inst;
1110# if LIBCOPP_MACRO_ENABLE_MULTI_THREAD
1111 LIBCOPP_COPP_NAMESPACE_ID::util::lock::lock_holder<LIBCOPP_COPP_NAMESPACE_ID::util::lock::spin_lock> lock_guard{
1115 using iter_type =
typename container_type::iterator;
1116 iter_type iter = tasks_.find(
id);
1117 if (tasks_.end() == iter) {
1118 return LIBCOPP_COPP_NAMESPACE_ID::COPP_EC_NOT_FOUND;
1120 if (
nullptr != confirm_context && iter->second.task_.get_context().get() != confirm_context) {
1121 return LIBCOPP_COPP_NAMESPACE_ID::COPP_EC_NOT_FOUND;
1125 task_inst = std::move(iter->second.task_);
1127 remove_timeout_timer(iter->second);
1131 if (task_inst.get_context()) {
1132# if defined(LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER) && LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER
1133 using task_manager_helper =
typename task_type::task_manager_helper;
1135 task_manager_helper::cleanup_task_manager(*task_inst.get_context(),
reinterpret_cast<void *
>(
this));
1138 task_status_type task_status = task_inst.get_status();
1139 if (task_status > task_status_type::kCreated && task_status < task_status_type::kDone) {
1140 return task_inst.kill(task_status_type::kKilled);
1144 return LIBCOPP_COPP_NAMESPACE_ID::COPP_EC_SUCCESS;
1152 const task_type *find_task(id_type
id)
noexcept {
1153 if (flags_ &
static_cast<uint32_t
>(flag_type::kTimerReset)) {
1157# if LIBCOPP_MACRO_ENABLE_MULTI_THREAD
1158 LIBCOPP_COPP_NAMESPACE_ID::util::lock::lock_holder<LIBCOPP_COPP_NAMESPACE_ID::util::lock::spin_lock> lock_guard{
1162 auto iter = tasks_.find(
id);
1163 if (tasks_.end() == iter) {
1167 return &iter->second.task_;
1170 int start(id_type
id) {
1171 if (flags_ &
static_cast<uint32_t
>(flag_type::kTimerReset)) {
1172 return LIBCOPP_COPP_NAMESPACE_ID::COPP_EC_IN_RESET;
1175 task_type task_inst;
1177# if LIBCOPP_MACRO_ENABLE_MULTI_THREAD
1178 LIBCOPP_COPP_NAMESPACE_ID::util::lock::lock_holder<LIBCOPP_COPP_NAMESPACE_ID::util::lock::spin_lock> lock_guard{
1182 using iter_type =
typename container_type::iterator;
1183 iter_type iter = tasks_.find(
id);
1184 if (tasks_.end() == iter)
return LIBCOPP_COPP_NAMESPACE_ID::COPP_EC_NOT_FOUND;
1186 task_inst = iter->second.task_;
1190 if (task_inst.get_context()) {
1194 if (task_inst.is_exiting()) {
1195 remove_task(
id, task_inst);
1198 return LIBCOPP_COPP_NAMESPACE_ID::COPP_EC_SUCCESS;
1200 return LIBCOPP_COPP_NAMESPACE_ID::COPP_EC_NOT_FOUND;
1204 int cancel(id_type
id) {
1205 if (flags_ &
static_cast<uint32_t
>(flag_type::kTimerReset)) {
1206 return LIBCOPP_COPP_NAMESPACE_ID::COPP_EC_IN_RESET;
1209 task_type task_inst;
1211# if LIBCOPP_MACRO_ENABLE_MULTI_THREAD
1212 LIBCOPP_COPP_NAMESPACE_ID::util::lock::lock_holder<LIBCOPP_COPP_NAMESPACE_ID::util::lock::spin_lock> lock_guard{
1216 using iter_type =
typename container_type::iterator;
1217 iter_type iter = tasks_.find(
id);
1218 if (tasks_.end() == iter) {
1219 return LIBCOPP_COPP_NAMESPACE_ID::COPP_EC_NOT_FOUND;
1222 task_inst = std::move(iter->second.task_);
1224 remove_timeout_timer(iter->second);
1229 if (task_inst.get_context()) {
1230# if defined(LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER) && LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER
1231 using task_manager_helper =
typename task_type::task_manager_helper;
1233 task_manager_helper::cleanup_task_manager(*task_inst.get_context(),
reinterpret_cast<void *
>(
this));
1236 return LIBCOPP_COPP_NAMESPACE_ID::COPP_EC_SUCCESS;
1238 return LIBCOPP_COPP_NAMESPACE_ID::COPP_EC_NOT_FOUND;
1242 int kill(id_type
id, task_status_type target_status) {
1243 if (flags_ &
static_cast<uint32_t
>(flag_type::kTimerReset)) {
1244 return LIBCOPP_COPP_NAMESPACE_ID::COPP_EC_IN_RESET;
1247 task_type task_inst;
1249# if LIBCOPP_MACRO_ENABLE_MULTI_THREAD
1250 LIBCOPP_COPP_NAMESPACE_ID::util::lock::lock_holder<LIBCOPP_COPP_NAMESPACE_ID::util::lock::spin_lock> lock_guard{
1254 using iter_type =
typename container_type::iterator;
1255 iter_type iter = tasks_.find(
id);
1256 if (tasks_.end() == iter) {
1257 return LIBCOPP_COPP_NAMESPACE_ID::COPP_EC_NOT_FOUND;
1260 task_inst = std::move(iter->second.task_);
1262 remove_timeout_timer(iter->second);
1267 if (task_inst.get_context()) {
1268# if defined(LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER) && LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER
1269 using task_manager_helper =
typename task_type::task_manager_helper;
1271 task_manager_helper::cleanup_task_manager(*task_inst.get_context(),
reinterpret_cast<void *
>(
this));
1273 task_inst.kill(target_status);
1274 return LIBCOPP_COPP_NAMESPACE_ID::COPP_EC_SUCCESS;
1276 return LIBCOPP_COPP_NAMESPACE_ID::COPP_EC_NOT_FOUND;
1280 int kill(id_type
id) {
return kill(
id, task_status_type::kKilled); }
1290 int tick(time_t sec,
int nsec = 0) {
1293 if (sec < last_tick_time_.tv_sec || (sec == last_tick_time_.tv_sec && nsec <= last_tick_time_.tv_nsec)) {
1297 now_tick_time.
tv_sec = sec;
1301 flag_guard_type tick_flag(&flags_, flag_type::kTimerTick);
1303 return LIBCOPP_COPP_NAMESPACE_ID::COPP_EC_SUCCESS;
1306 if (flags_ &
static_cast<uint32_t
>(flag_type::kTimerReset)) {
1307 return LIBCOPP_COPP_NAMESPACE_ID::COPP_EC_IN_RESET;
1311 if (0 == last_tick_time_.tv_sec && 0 == last_tick_time_.tv_nsec) {
1313# if LIBCOPP_MACRO_ENABLE_MULTI_THREAD
1314 LIBCOPP_COPP_NAMESPACE_ID::util::lock::lock_holder<LIBCOPP_COPP_NAMESPACE_ID::util::lock::spin_lock> lock_guard{
1318 std::set<detail::task_timer_node<id_type>> real_checkpoints;
1320 task_timeout_timer_.end() != iter; ++iter) {
1324 real_checkpoints.insert(new_checkpoint);
1327 task_timeout_timer_.swap(real_checkpoints);
1329 task_timeout_timer_.end() != iter; ++iter) {
1330 const typename std::set<detail::task_timer_node<id_type>>::value_type &checkpoint = *iter;
1331 using co_iter_type =
typename container_type::iterator;
1332 co_iter_type co_iter = tasks_.find(checkpoint.task_id);
1334 if (tasks_.end() != co_iter) {
1335 co_iter->second.timer_node.set(task_timeout_timer_, iter);
1338 last_tick_time_ = now_tick_time;
1339 return LIBCOPP_COPP_NAMESPACE_ID::COPP_EC_SUCCESS;
1343 while (
false == task_timeout_timer_.empty()) {
1344 task_type task_inst;
1348# if LIBCOPP_MACRO_ENABLE_MULTI_THREAD
1349 LIBCOPP_COPP_NAMESPACE_ID::util::lock::lock_holder<LIBCOPP_COPP_NAMESPACE_ID::util::lock::spin_lock> lock_guard{
1353 const typename std::set<detail::task_timer_node<id_type>>::value_type &timer_node_value =
1354 *task_timeout_timer_.begin();
1356 if (now_tick_time <= timer_node_value.expired_time) {
1361 using iter_type =
typename container_type::iterator;
1363 iter_type iter = tasks_.find(timer_node_value.task_id);
1365 if (tasks_.end() != iter) {
1367 task_inst = std::move(iter->second.task_);
1369 remove_timeout_timer(iter->second);
1375 if (!task_inst.is_exiting()) {
1376# if defined(LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER) && LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER
1377 using task_manager_helper =
typename task_type::task_manager_helper;
1379 task_manager_helper::cleanup_task_manager(*task_inst.get_context(),
reinterpret_cast<void *
>(
this));
1381 task_inst.kill(task_status_type::kTimeout);
1385 last_tick_time_ = now_tick_time;
1386 return LIBCOPP_COPP_NAMESPACE_ID::COPP_EC_SUCCESS;
1393 size_t get_tick_checkpoint_size() const LIBCOPP_MACRO_NOEXCEPT {
return task_timeout_timer_.size(); }
1399 size_t get_task_size() const LIBCOPP_MACRO_NOEXCEPT {
return tasks_.size(); }
1405 detail::tickspec_t get_last_tick_time() const LIBCOPP_MACRO_NOEXCEPT {
return last_tick_time_; }
1411 inline const container_type &get_container() const LIBCOPP_MACRO_NOEXCEPT {
return tasks_; }
1417 inline const std::set<detail::task_timer_node<id_type>> &get_checkpoints() const LIBCOPP_MACRO_NOEXCEPT {
1418 return task_timeout_timer_;
1422 void set_timeout_timer(detail::task_manager_node<task_type> &node, time_t timeout_sec,
int timeout_nsec) {
1423 remove_timeout_timer(node);
1425 if (timeout_sec <= 0 && timeout_nsec <= 0) {
1429 if (!node.task_.get_context()) {
1434 timer_node_value.
task_id = node.task_.get_id();
1438 std::pair<typename std::set<detail::task_timer_node<id_type>>::iterator,
bool> res =
1439 task_timeout_timer_.insert(timer_node_value);
1441 node.timer_node.set(task_timeout_timer_, res.first);
1445 void remove_timeout_timer(detail::task_manager_node<task_type> &node) {
1446 if (node.timer_node.valid(task_timeout_timer_)) {
1447 task_timeout_timer_.erase(node.timer_node.release(task_timeout_timer_));
1451# if defined(LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER) && LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER
1452 static void task_cleanup_callback(
void *self_ptr, task_context_base<TVALUE> &task_inst) {
1453 if (
nullptr == self_ptr) {
1457 reinterpret_cast<self_type *
>(self_ptr)->remove_task(task_inst.get_id(), &task_inst);
1462 container_type tasks_;
1464 std::set<detail::task_timer_node<id_type>> task_timeout_timer_;
1466# if LIBCOPP_MACRO_ENABLE_MULTI_THREAD
1467 LIBCOPP_COPP_NAMESPACE_ID::util::lock::spin_lock action_lock_;
1473LIBCOPP_COTASK_NAMESPACE_END
LIBCOPP_COTASK_API bool is_exiting() const LIBCOPP_MACRO_NOEXCEPT
check if a cotask is exiting
LIBCOPP_UTIL_FORCEINLINE id_type get_id() const LIBCOPP_MACRO_NOEXCEPT
int start(id_type id, void *priv_data=nullptr)
void remove_timeout_timer(detail::task_manager_node< task_type > &node)
const container_type & get_container() const LIBCOPP_MACRO_NOEXCEPT
task container, this api is just used for provide information to users
int kill(id_type id, enum EN_TASK_STATUS status, void *priv_data=nullptr)
int kill(id_type id, void *priv_data=nullptr)
detail::tickspec_t get_last_tick_time() const LIBCOPP_MACRO_NOEXCEPT
get last tick time
LIBCOPP_COPP_NAMESPACE_ID::memory::default_strong_rc_ptr< self_type > ptr_type
const std::set< detail::task_timer_node< id_type > > & get_checkpoints() const LIBCOPP_MACRO_NOEXCEPT
get all task checkpoints, this api is just used for provide information to users
int remove_task(id_type id)
remove task in this manager
typename task_type::id_type id_type
static ptr_type create()
create a new task manager
size_t get_task_size() const LIBCOPP_MACRO_NOEXCEPT
get task number in this manager
task_manager< task_type > self_type
int remove_task(id_type id, const task_type *confirm_ptr)
remove task in this manager
int tick(time_t sec, int nsec=0)
active tick event and deal with clock
container_type container_t
int cancel(id_type id, void *priv_data=nullptr)
int add_task(const task_ptr_type &task, time_t timeout_sec, int timeout_nsec)
add task to manager please make the task has method of get_id() and will return a unique id
task_ptr_type find_task(id_type id)
find task by id
detail::tickspec_t last_tick_time_
typename task_type::ptr_type task_ptr_type
int remove_task(id_type id, const task_ptr_type &confirm_ptr)
remove task in this manager
std::set< detail::task_timer_node< id_type > > task_timeout_timer_
size_t get_tick_checkpoint_size() const LIBCOPP_MACRO_NOEXCEPT
get timeout checkpoint number in this manager
int resume(id_type id, void *priv_data=nullptr)
std::unordered_map< typename task_type::id_type, detail::task_manager_node< task_type > > container_type
void set_timeout_timer(detail::task_manager_node< task_type > &node, time_t timeout_sec, int timeout_nsec)
int set_timeout(id_type id, time_t timeout_sec, int timeout_nsec)
set or update task timeout
int add_task(const task_ptr_type &task)
add task to manager please make the task has method of get_id() and will return a unique id
typename impl::task_impl::id_type id_type
LIBCOPP_COPP_NAMESPACE_ID::memory::intrusive_ptr< self_type > ptr_type
struct LIBCOPP_COTASK_API_HEAD_ONLY task_manager_node
my_task_t::ptr_t task_ptr_type
std::set< task_timer_node_type > task_timer_container_type
typename task< TCO_MACRO >::id_type task_id_type
typename task< TCO_MACRO >::ptr_type task_ptr_type
LIBCOPP_COPP_NAMESPACE_ID::util::iterator_guard< task_timer_container_type > timer_node
friend bool operator==(const task_timer_node &l, const task_timer_node &r)
friend bool operator!=(const task_timer_node &l, const task_timer_node &r)
friend bool operator>=(const task_timer_node &l, const task_timer_node &r)
friend bool operator<(const task_timer_node &l, const task_timer_node &r)
friend bool operator>(const task_timer_node &l, const task_timer_node &r)
friend bool operator<=(const task_timer_node &l, const task_timer_node &r)
friend bool operator!=(const tickspec_t &l, const tickspec_t &r)
friend bool operator>=(const tickspec_t &l, const tickspec_t &r)
friend bool operator==(const tickspec_t &l, const tickspec_t &r)
friend bool operator<(const tickspec_t &l, const tickspec_t &r)
friend bool operator>(const tickspec_t &l, const tickspec_t &r)
friend bool operator<=(const tickspec_t &l, const tickspec_t &r)
flag_guard_type(int *flags, typename flag_type::type v)
class LIBCOPP_COTASK_API_HEAD_ONLY task_manager