5 #include <libcopp/utils/config/libcopp_build_features.h>
18 #include <unordered_map>
21 #ifdef __cpp_impl_three_way_comparison
25 #if defined(LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR) && LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR
35 LIBCOPP_COTASK_NAMESPACE_BEGIN
46 #ifdef __cpp_impl_three_way_comparison
73 template <
class TTASK_ID_TYPE>
82 #ifdef __cpp_impl_three_way_comparison
129 template <
class TTask>
132 template <
class TCO_MACRO>
137 typename std::set<task_timer_node<typename task<TCO_MACRO>::id_type>>::iterator
timer_node;
140 #if defined(LIBCOPP_MACRO_ENABLE_STD_COROUTINE) && LIBCOPP_MACRO_ENABLE_STD_COROUTINE
141 template <
class TVALUE,
class TPRIVATE_DATA,
class TERROR_TRANSFORM>
142 struct LIBCOPP_COTASK_API_HEAD_ONLY
task_manager_node<task_future<TVALUE, TPRIVATE_DATA, TERROR_TRANSFORM>> {
143 using task_type = task_future<TVALUE, TPRIVATE_DATA, TERROR_TRANSFORM>;
146 typename std::set<task_timer_node<typename task_type::id_type>>::iterator timer_node;
152 template <
typename TTask>
158 template <
typename TCO_MACRO>
162 using container_type = std::unordered_map<typename task_type::id_type, detail::task_manager_node<task_type>>;
171 EN_TM_IN_TICK = 0x01,
172 EN_TM_IN_RESET = 0x02,
186 struct flag_guard_type {
190 if (
nullptr == data_ || (*data_ & flag_)) {
191 flag_ = flag_type::EN_TM_NONE;
203 inline operator bool() {
return nullptr != data_ && flag_type::EN_TM_NONE != flag_; }
208 last_tick_time_.tv_sec = 0;
209 last_tick_time_.tv_nsec = 0;
218 flag_guard_type reset_flag(&flags_, flag_type::EN_TM_IN_RESET);
223 std::vector<task_ptr_type> all_tasks;
226 #if !defined(LIBCOPP_DISABLE_ATOMIC_LOCK) || !(LIBCOPP_DISABLE_ATOMIC_LOCK)
227 LIBCOPP_COPP_NAMESPACE_ID::util::lock::lock_holder<LIBCOPP_COPP_NAMESPACE_ID::util::lock::spin_lock> lock_guard{
231 for (
typename container_type::iterator iter = tasks_.begin(); iter != tasks_.end(); ++iter) {
232 all_tasks.push_back(iter->second.task_);
233 remove_timeout_timer(iter->second);
237 task_timeout_timer_.clear();
239 last_tick_time_.tv_sec = 0;
240 last_tick_time_.tv_nsec = 0;
244 for (
typename std::vector<task_ptr_type>::iterator iter = all_tasks.begin(); iter != all_tasks.end(); ++iter) {
245 if (!(*iter)->is_exiting()) {
276 if (flags_ & flag_type::EN_TM_IN_RESET) {
286 detail::task_manager_node<task_type> task_node;
287 task_node.task_ =
task;
288 task_node.timer_node = task_timeout_timer_.end();
290 if (!task_node.task_) {
291 assert(task_node.task_);
296 #if !defined(LIBCOPP_DISABLE_ATOMIC_LOCK) || !(LIBCOPP_DISABLE_ATOMIC_LOCK)
297 LIBCOPP_COPP_NAMESPACE_ID::util::lock::lock_holder<LIBCOPP_COPP_NAMESPACE_ID::util::lock::spin_lock> lock_guard{
302 if (tasks_.end() != tasks_.find(task_id)) {
306 #if defined(LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER) && LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER
307 using task_manager_helper =
typename task_type::task_manager_helper;
308 if (!task_manager_helper::setup_task_manager(*
task,
reinterpret_cast<void *
>(
this), &task_cleanup_callback)) {
314 std::pair<typename container_type::iterator, bool> res = tasks_.insert(pair_type(task_id, task_node));
315 if (
false == res.second) {
316 #if defined(LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER) && LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER
317 task_manager_helper::cleanup_task_manager(*
task,
reinterpret_cast<void *
>(
this));
323 set_timeout_timer(res.first->second, timeout_sec, timeout_nsec);
352 if (flags_ & flag_type::EN_TM_IN_RESET) {
357 #if !defined(LIBCOPP_DISABLE_ATOMIC_LOCK) || !(LIBCOPP_DISABLE_ATOMIC_LOCK)
358 LIBCOPP_COPP_NAMESPACE_ID::util::lock::lock_holder<LIBCOPP_COPP_NAMESPACE_ID::util::lock::spin_lock> lock_guard{
362 using iter_type =
typename container_type::iterator;
363 iter_type iter = tasks_.find(
id);
366 set_timeout_timer(iter->second, timeout_sec, timeout_nsec);
394 if (flags_ & flag_type::EN_TM_IN_RESET) {
400 #if !defined(LIBCOPP_DISABLE_ATOMIC_LOCK) || !(LIBCOPP_DISABLE_ATOMIC_LOCK)
401 LIBCOPP_COPP_NAMESPACE_ID::util::lock::lock_holder<LIBCOPP_COPP_NAMESPACE_ID::util::lock::spin_lock> lock_guard{
405 using iter_type =
typename container_type::iterator;
406 iter_type iter = tasks_.find(
id);
407 if (tasks_.end() == iter) {
410 if (
nullptr != confirm_ptr && iter->second.task_.get() != confirm_ptr) {
415 task_inst = std::move(iter->second.task_);
417 remove_timeout_timer(iter->second);
422 #if defined(LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER) && LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER
423 using task_manager_helper =
typename task_type::task_manager_helper;
425 task_manager_helper::cleanup_task_manager(*task_inst,
reinterpret_cast<void *
>(
this));
443 if (flags_ & flag_type::EN_TM_IN_RESET) {
447 #if !defined(LIBCOPP_DISABLE_ATOMIC_LOCK) || !(LIBCOPP_DISABLE_ATOMIC_LOCK)
448 LIBCOPP_COPP_NAMESPACE_ID::util::lock::lock_holder<LIBCOPP_COPP_NAMESPACE_ID::util::lock::spin_lock> lock_guard{
452 using iter_type =
typename container_type::iterator;
453 iter_type iter = tasks_.find(
id);
456 return iter->second.task_;
462 #if defined(LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR) && LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR
463 int start(id_type
id,
void *priv_data =
nullptr) {
464 std::list<std::exception_ptr> eptrs;
465 int ret = start(
id, eptrs, priv_data);
466 task_type::maybe_rethrow(eptrs);
470 int start(id_type
id, std::list<std::exception_ptr> &unhandled,
void *priv_data =
nullptr) LIBCOPP_MACRO_NOEXCEPT {
474 if (flags_ & flag_type::EN_TM_IN_RESET) {
480 #if !defined(LIBCOPP_DISABLE_ATOMIC_LOCK) || !(LIBCOPP_DISABLE_ATOMIC_LOCK)
481 LIBCOPP_COPP_NAMESPACE_ID::util::lock::lock_holder<LIBCOPP_COPP_NAMESPACE_ID::util::lock::spin_lock> lock_guard{
485 using iter_type =
typename container_type::iterator;
486 iter_type iter = tasks_.find(
id);
489 task_inst = iter->second.task_;
494 #if defined(LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR) && LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR
495 int ret = task_inst->start(unhandled, priv_data);
497 int ret = task_inst->start(priv_data);
511 #if defined(LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR) && LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR
512 int resume(id_type
id,
void *priv_data =
nullptr) {
513 std::list<std::exception_ptr> eptrs;
514 int ret = resume(
id, eptrs, priv_data);
515 task_type::maybe_rethrow(eptrs);
519 int resume(id_type
id, std::list<std::exception_ptr> &unhandled,
void *priv_data =
nullptr) LIBCOPP_MACRO_NOEXCEPT {
523 if (flags_ & flag_type::EN_TM_IN_RESET) {
529 #if !defined(LIBCOPP_DISABLE_ATOMIC_LOCK) || !(LIBCOPP_DISABLE_ATOMIC_LOCK)
530 LIBCOPP_COPP_NAMESPACE_ID::util::lock::lock_holder<LIBCOPP_COPP_NAMESPACE_ID::util::lock::spin_lock> lock_guard{
534 using iter_type =
typename container_type::iterator;
535 iter_type iter = tasks_.find(
id);
538 task_inst = iter->second.task_;
543 #if defined(LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR) && LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR
544 int ret = task_inst->resume(unhandled, priv_data);
546 int ret = task_inst->resume(priv_data);
560 #if defined(LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR) && LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR
561 int cancel(id_type
id,
void *priv_data =
nullptr) {
562 std::list<std::exception_ptr> eptrs;
563 int ret = cancel(
id, eptrs, priv_data);
564 task_type::maybe_rethrow(eptrs);
568 int cancel(id_type
id, std::list<std::exception_ptr> &unhandled,
void *priv_data =
nullptr) LIBCOPP_MACRO_NOEXCEPT {
572 if (flags_ & flag_type::EN_TM_IN_RESET) {
578 #if !defined(LIBCOPP_DISABLE_ATOMIC_LOCK) || !(LIBCOPP_DISABLE_ATOMIC_LOCK)
579 LIBCOPP_COPP_NAMESPACE_ID::util::lock::lock_holder<LIBCOPP_COPP_NAMESPACE_ID::util::lock::spin_lock> lock_guard{
583 using iter_type =
typename container_type::iterator;
584 iter_type iter = tasks_.find(
id);
585 if (tasks_.end() == iter) {
589 task_inst = std::move(iter->second.task_);
591 remove_timeout_timer(iter->second);
597 #if defined(LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER) && LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER
598 using task_manager_helper =
typename task_type::task_manager_helper;
600 task_manager_helper::cleanup_task_manager(*task_inst,
reinterpret_cast<void *
>(
this));
602 #if defined(LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR) && LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR
603 return task_inst->cancel(unhandled, priv_data);
605 return task_inst->cancel(priv_data);
612 #if defined(LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR) && LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR
613 int kill(id_type
id,
enum EN_TASK_STATUS status,
void *priv_data =
nullptr) {
614 std::list<std::exception_ptr> eptrs;
615 int ret = kill(
id, eptrs, status, priv_data);
616 task_type::maybe_rethrow(eptrs);
620 int kill(id_type
id, std::list<std::exception_ptr> &unhandled,
enum EN_TASK_STATUS status,
621 void *priv_data =
nullptr) LIBCOPP_MACRO_NOEXCEPT {
625 if (flags_ & flag_type::EN_TM_IN_RESET) {
631 #if !defined(LIBCOPP_DISABLE_ATOMIC_LOCK) || !(LIBCOPP_DISABLE_ATOMIC_LOCK)
632 LIBCOPP_COPP_NAMESPACE_ID::util::lock::lock_holder<LIBCOPP_COPP_NAMESPACE_ID::util::lock::spin_lock> lock_guard{
636 using iter_type =
typename container_type::iterator;
637 iter_type iter = tasks_.find(
id);
638 if (tasks_.end() == iter) {
642 task_inst = std::move(iter->second.task_);
644 remove_timeout_timer(iter->second);
650 #if defined(LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER) && LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER
651 using task_manager_helper =
typename task_type::task_manager_helper;
653 task_manager_helper::cleanup_task_manager(*task_inst,
reinterpret_cast<void *
>(
this));
655 #if defined(LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR) && LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR
656 return task_inst->kill(unhandled, status, priv_data);
658 return task_inst->kill(status, priv_data);
675 int tick(time_t sec,
int nsec = 0) {
678 if (sec < last_tick_time_.tv_sec || (sec == last_tick_time_.tv_sec && nsec <= last_tick_time_.tv_nsec)) {
682 now_tick_time.
tv_sec = sec;
686 flag_guard_type tick_flag(&flags_, flag_type::EN_TM_IN_TICK);
691 if (flags_ & flag_type::EN_TM_IN_RESET) {
696 if (0 == last_tick_time_.tv_sec && 0 == last_tick_time_.tv_nsec) {
698 #if !defined(LIBCOPP_DISABLE_ATOMIC_LOCK) || !(LIBCOPP_DISABLE_ATOMIC_LOCK)
699 LIBCOPP_COPP_NAMESPACE_ID::util::lock::lock_holder<LIBCOPP_COPP_NAMESPACE_ID::util::lock::spin_lock> lock_guard{
703 std::set<detail::task_timer_node<id_type>> real_checkpoints;
705 task_timeout_timer_.end() != iter; ++iter) {
709 real_checkpoints.insert(new_checkpoint);
712 task_timeout_timer_.swap(real_checkpoints);
714 task_timeout_timer_.end() != iter; ++iter) {
715 const typename std::set<detail::task_timer_node<id_type>>
::value_type &checkpoint = *iter;
716 using co_iter_type =
typename container_type::iterator;
717 co_iter_type co_iter = tasks_.find(checkpoint.task_id);
719 if (tasks_.end() != co_iter) {
720 co_iter->second.timer_node = iter;
723 last_tick_time_ = now_tick_time;
727 #if defined(LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR) && LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR
728 std::list<std::exception_ptr> eptrs;
731 while (
false == task_timeout_timer_.empty()) {
736 #if !defined(LIBCOPP_DISABLE_ATOMIC_LOCK) || !(LIBCOPP_DISABLE_ATOMIC_LOCK)
737 LIBCOPP_COPP_NAMESPACE_ID::util::lock::lock_holder<LIBCOPP_COPP_NAMESPACE_ID::util::lock::spin_lock> lock_guard{
741 const typename std::set<detail::task_timer_node<id_type>>
::value_type &timer_node =
742 *task_timeout_timer_.begin();
744 if (now_tick_time <= timer_node.expired_time) {
749 using iter_type =
typename container_type::iterator;
751 iter_type iter = tasks_.find(timer_node.task_id);
753 if (tasks_.end() != iter) {
755 task_inst = std::move(iter->second.task_);
757 remove_timeout_timer(iter->second);
763 if (task_inst && !task_inst->is_exiting()) {
764 #if defined(LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER) && LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER
765 using task_manager_helper =
typename task_type::task_manager_helper;
767 task_manager_helper::cleanup_task_manager(*task_inst,
reinterpret_cast<void *
>(
this));
769 #if defined(LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR) && LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR
777 last_tick_time_ = now_tick_time;
779 #if defined(LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR) && LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR
780 task_type::maybe_rethrow(eptrs);
814 return task_timeout_timer_;
818 void set_timeout_timer(detail::task_manager_node<task_type> &node, time_t timeout_sec,
int timeout_nsec) {
819 remove_timeout_timer(node);
821 if (timeout_sec <= 0 && timeout_nsec <= 0) {
830 timer_node.
task_id = node.task_->get_id();
834 std::pair<typename std::set<detail::task_timer_node<id_type>>::iterator,
bool> res =
835 task_timeout_timer_.insert(timer_node);
837 node.timer_node = res.first;
842 if (node.timer_node != task_timeout_timer_.end()) {
843 task_timeout_timer_.erase(node.timer_node);
844 node.timer_node = task_timeout_timer_.end();
848 #if defined(LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER) && LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER
849 static void task_cleanup_callback(
void *self_ptr, task_type &task_inst) {
850 if (
nullptr == self_ptr) {
854 reinterpret_cast<self_type *
>(self_ptr)->remove_task(task_inst.get_id(), &task_inst);
863 #if !defined(LIBCOPP_DISABLE_ATOMIC_LOCK) || !(LIBCOPP_DISABLE_ATOMIC_LOCK)
869 #if defined(LIBCOPP_MACRO_ENABLE_STD_COROUTINE) && LIBCOPP_MACRO_ENABLE_STD_COROUTINE
873 template <
class TVALUE,
class TPRIVATE_DATA,
class TERROR_TRANSFORM>
874 class LIBCOPP_COTASK_API_HEAD_ONLY
task_manager<task_future<TVALUE, TPRIVATE_DATA, TERROR_TRANSFORM>> {
876 using task_type = task_future<TVALUE, TPRIVATE_DATA, TERROR_TRANSFORM>;
877 using container_type = std::unordered_map<typename task_type::id_type, detail::task_manager_node<task_type>>;
878 using id_type =
typename task_type::id_type;
879 using task_status_type =
typename task_type::task_status_type;
880 using self_type = task_manager<task_type>;
881 using ptr_type = std::shared_ptr<self_type>;
883 enum class flag_type : uint32_t{
890 struct flag_guard_type {
893 inline flag_guard_type(uint32_t *flags, flag_type v) : data_(flags), flag_(v) {
894 if (
nullptr == data_ || (*data_ &
static_cast<uint32_t
>(flag_))) {
895 flag_ = flag_type::kNone;
898 (*data_) |=
static_cast<uint32_t
>(flag_);
901 inline ~flag_guard_type() {
903 (*data_) &= ~static_cast<uint32_t>(flag_);
907 inline operator bool() {
return nullptr != data_ && flag_type::kNone != flag_; }
912 last_tick_time_.tv_sec = 0;
913 last_tick_time_.tv_nsec = 0;
922 flag_guard_type reset_flag(&flags_, flag_type::kTimerReset);
927 std::vector<task_type> all_tasks;
930 # if !defined(LIBCOPP_DISABLE_ATOMIC_LOCK) || !(LIBCOPP_DISABLE_ATOMIC_LOCK)
931 LIBCOPP_COPP_NAMESPACE_ID::util::lock::lock_holder<LIBCOPP_COPP_NAMESPACE_ID::util::lock::spin_lock> lock_guard{
935 for (
typename container_type::iterator iter = tasks_.begin(); iter != tasks_.end(); ++iter) {
936 all_tasks.push_back(iter->second.task_);
937 remove_timeout_timer(iter->second);
941 task_timeout_timer_.clear();
943 last_tick_time_.tv_sec = 0;
944 last_tick_time_.tv_nsec = 0;
948 for (
typename std::vector<task_type>::iterator iter = all_tasks.begin(); iter != all_tasks.end(); ++iter) {
949 if (!(*iter).is_exiting()) {
950 # if defined(LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER) && LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER
951 using task_manager_helper =
typename task_type::task_manager_helper;
953 task_manager_helper::cleanup_task_manager(*(*iter).get_context(),
reinterpret_cast<void *
>(
this));
956 (*iter).kill(task_status_type::kKilled);
965 static ptr_type create() noexcept {
return std::make_shared<self_type>(); }
980 int add_task(
const task_type &
task, time_t timeout_sec,
int timeout_nsec) noexcept {
981 if (flags_ &
static_cast<uint32_t
>(flag_type::kTimerReset)) {
991 detail::task_manager_node<task_type> task_node;
992 task_node.task_ =
task;
993 task_node.timer_node = task_timeout_timer_.end();
996 # if !defined(LIBCOPP_DISABLE_ATOMIC_LOCK) || !(LIBCOPP_DISABLE_ATOMIC_LOCK)
997 LIBCOPP_COPP_NAMESPACE_ID::util::lock::lock_holder<LIBCOPP_COPP_NAMESPACE_ID::util::lock::spin_lock> lock_guard{
1002 if (tasks_.end() != tasks_.find(task_id)) {
1006 # if defined(LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER) && LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER
1007 using task_manager_helper =
typename task_type::task_manager_helper;
1008 if (!task_manager_helper::setup_task_manager(*
task.get_context(),
reinterpret_cast<void *
>(
this),
1009 &task_cleanup_callback)) {
1015 std::pair<typename container_type::iterator, bool> res = tasks_.insert(pair_type(task_id, task_node));
1016 if (
false == res.second) {
1017 # if defined(LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER) && LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER
1018 task_manager_helper::cleanup_task_manager(*
task.get_context(),
reinterpret_cast<void *
>(
this));
1024 set_timeout_timer(res.first->second, timeout_sec, timeout_nsec);
1036 int add_task(
const task_type &
task) noexcept {
return add_task(
task, 0, 0); }
1052 int set_timeout(id_type
id, time_t timeout_sec,
int timeout_nsec) noexcept {
1053 if (flags_ &
static_cast<uint32_t
>(flag_type::kTimerReset)) {
1058 # if !defined(LIBCOPP_DISABLE_ATOMIC_LOCK) || !(LIBCOPP_DISABLE_ATOMIC_LOCK)
1059 LIBCOPP_COPP_NAMESPACE_ID::util::lock::lock_holder<LIBCOPP_COPP_NAMESPACE_ID::util::lock::spin_lock> lock_guard{
1063 using iter_type =
typename container_type::iterator;
1064 iter_type iter = tasks_.find(
id);
1067 set_timeout_timer(iter->second, timeout_sec, timeout_nsec);
1079 inline int remove_task(id_type
id,
const task_type &confirm_task) {
1080 return remove_task(
id, confirm_task.get_context().get());
1088 inline int remove_task(id_type
id) {
return remove_task(
id,
nullptr); }
1096 int remove_task(id_type
id,
const task_context_base<TVALUE> *confirm_context) {
1097 if (flags_ &
static_cast<uint32_t
>(flag_type::kTimerReset)) {
1101 task_type task_inst;
1103 # if !defined(LIBCOPP_DISABLE_ATOMIC_LOCK) || !(LIBCOPP_DISABLE_ATOMIC_LOCK)
1104 LIBCOPP_COPP_NAMESPACE_ID::util::lock::lock_holder<LIBCOPP_COPP_NAMESPACE_ID::util::lock::spin_lock> lock_guard{
1108 using iter_type =
typename container_type::iterator;
1109 iter_type iter = tasks_.find(
id);
1110 if (tasks_.end() == iter) {
1113 if (
nullptr != confirm_context && iter->second.task_.get_context().get() != confirm_context) {
1118 task_inst = std::move(iter->second.task_);
1120 remove_timeout_timer(iter->second);
1124 if (task_inst.get_context()) {
1125 # if defined(LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER) && LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER
1126 using task_manager_helper =
typename task_type::task_manager_helper;
1128 task_manager_helper::cleanup_task_manager(*task_inst.get_context(),
reinterpret_cast<void *
>(
this));
1131 task_status_type task_status = task_inst.get_status();
1132 if (task_status > task_status_type::kCreated && task_status < task_status_type::kDone) {
1133 return task_inst.kill(task_status_type::kKilled);
1145 const task_type *find_task(id_type
id) noexcept {
1146 if (flags_ &
static_cast<uint32_t
>(flag_type::kTimerReset)) {
1150 # if !defined(LIBCOPP_DISABLE_ATOMIC_LOCK) || !(LIBCOPP_DISABLE_ATOMIC_LOCK)
1151 LIBCOPP_COPP_NAMESPACE_ID::util::lock::lock_holder<LIBCOPP_COPP_NAMESPACE_ID::util::lock::spin_lock> lock_guard{
1155 auto iter = tasks_.find(
id);
1156 if (tasks_.end() == iter) {
1160 return &iter->second.task_;
1163 int start(id_type
id) {
1164 if (flags_ &
static_cast<uint32_t
>(flag_type::kTimerReset)) {
1168 task_type task_inst;
1170 # if !defined(LIBCOPP_DISABLE_ATOMIC_LOCK) || !(LIBCOPP_DISABLE_ATOMIC_LOCK)
1171 LIBCOPP_COPP_NAMESPACE_ID::util::lock::lock_holder<LIBCOPP_COPP_NAMESPACE_ID::util::lock::spin_lock> lock_guard{
1175 using iter_type =
typename container_type::iterator;
1176 iter_type iter = tasks_.find(
id);
1179 task_inst = iter->second.task_;
1183 if (task_inst.get_context()) {
1187 if (task_inst.is_exiting()) {
1188 remove_task(
id, task_inst);
1197 int cancel(id_type
id) {
1198 if (flags_ &
static_cast<uint32_t
>(flag_type::kTimerReset)) {
1202 task_type task_inst;
1204 # if !defined(LIBCOPP_DISABLE_ATOMIC_LOCK) || !(LIBCOPP_DISABLE_ATOMIC_LOCK)
1205 LIBCOPP_COPP_NAMESPACE_ID::util::lock::lock_holder<LIBCOPP_COPP_NAMESPACE_ID::util::lock::spin_lock> lock_guard{
1209 using iter_type =
typename container_type::iterator;
1210 iter_type iter = tasks_.find(
id);
1211 if (tasks_.end() == iter) {
1215 task_inst = std::move(iter->second.task_);
1217 remove_timeout_timer(iter->second);
1222 if (task_inst.get_context()) {
1223 # if defined(LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER) && LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER
1224 using task_manager_helper =
typename task_type::task_manager_helper;
1226 task_manager_helper::cleanup_task_manager(*task_inst.get_context(),
reinterpret_cast<void *
>(
this));
1235 int kill(id_type
id, task_status_type target_status) {
1236 if (flags_ &
static_cast<uint32_t
>(flag_type::kTimerReset)) {
1240 task_type task_inst;
1242 # if !defined(LIBCOPP_DISABLE_ATOMIC_LOCK) || !(LIBCOPP_DISABLE_ATOMIC_LOCK)
1243 LIBCOPP_COPP_NAMESPACE_ID::util::lock::lock_holder<LIBCOPP_COPP_NAMESPACE_ID::util::lock::spin_lock> lock_guard{
1247 using iter_type =
typename container_type::iterator;
1248 iter_type iter = tasks_.find(
id);
1249 if (tasks_.end() == iter) {
1253 task_inst = std::move(iter->second.task_);
1255 remove_timeout_timer(iter->second);
1260 if (task_inst.get_context()) {
1261 # if defined(LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER) && LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER
1262 using task_manager_helper =
typename task_type::task_manager_helper;
1264 task_manager_helper::cleanup_task_manager(*task_inst.get_context(),
reinterpret_cast<void *
>(
this));
1266 task_inst.kill(target_status);
1273 int kill(id_type
id) {
return kill(
id, task_status_type::kKilled); }
1283 int tick(time_t sec,
int nsec = 0) {
1286 if (sec < last_tick_time_.tv_sec || (sec == last_tick_time_.tv_sec && nsec <= last_tick_time_.tv_nsec)) {
1290 now_tick_time.
tv_sec = sec;
1294 flag_guard_type tick_flag(&flags_, flag_type::kTimerTick);
1299 if (flags_ &
static_cast<uint32_t
>(flag_type::kTimerReset)) {
1304 if (0 == last_tick_time_.tv_sec && 0 == last_tick_time_.tv_nsec) {
1306 # if !defined(LIBCOPP_DISABLE_ATOMIC_LOCK) || !(LIBCOPP_DISABLE_ATOMIC_LOCK)
1307 LIBCOPP_COPP_NAMESPACE_ID::util::lock::lock_holder<LIBCOPP_COPP_NAMESPACE_ID::util::lock::spin_lock> lock_guard{
1311 std::set<detail::task_timer_node<id_type>> real_checkpoints;
1313 task_timeout_timer_.end() != iter; ++iter) {
1317 real_checkpoints.insert(new_checkpoint);
1320 task_timeout_timer_.swap(real_checkpoints);
1322 task_timeout_timer_.end() != iter; ++iter) {
1323 const typename std::set<detail::task_timer_node<id_type>>
::value_type &checkpoint = *iter;
1324 using co_iter_type =
typename container_type::iterator;
1325 co_iter_type co_iter = tasks_.find(checkpoint.task_id);
1327 if (tasks_.end() != co_iter) {
1328 co_iter->second.timer_node = iter;
1331 last_tick_time_ = now_tick_time;
1336 while (
false == task_timeout_timer_.empty()) {
1337 task_type task_inst;
1341 # if !defined(LIBCOPP_DISABLE_ATOMIC_LOCK) || !(LIBCOPP_DISABLE_ATOMIC_LOCK)
1342 LIBCOPP_COPP_NAMESPACE_ID::util::lock::lock_holder<LIBCOPP_COPP_NAMESPACE_ID::util::lock::spin_lock> lock_guard{
1346 const typename std::set<detail::task_timer_node<id_type>>
::value_type &timer_node =
1347 *task_timeout_timer_.begin();
1349 if (now_tick_time <= timer_node.expired_time) {
1354 using iter_type =
typename container_type::iterator;
1356 iter_type iter = tasks_.find(timer_node.task_id);
1358 if (tasks_.end() != iter) {
1360 task_inst = std::move(iter->second.task_);
1362 remove_timeout_timer(iter->second);
1368 if (!task_inst.is_exiting()) {
1369 # if defined(LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER) && LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER
1370 using task_manager_helper =
typename task_type::task_manager_helper;
1372 task_manager_helper::cleanup_task_manager(*task_inst.get_context(),
reinterpret_cast<void *
>(
this));
1374 task_inst.kill(task_status_type::kTimeout);
1378 last_tick_time_ = now_tick_time;
1386 size_t get_tick_checkpoint_size()
const LIBCOPP_MACRO_NOEXCEPT {
return task_timeout_timer_.size(); }
1392 size_t get_task_size()
const LIBCOPP_MACRO_NOEXCEPT {
return tasks_.size(); }
1404 inline const container_type &get_container()
const LIBCOPP_MACRO_NOEXCEPT {
return tasks_; }
1410 inline const std::set<detail::task_timer_node<id_type>> &get_checkpoints()
const LIBCOPP_MACRO_NOEXCEPT {
1411 return task_timeout_timer_;
1415 void set_timeout_timer(detail::task_manager_node<task_type> &node, time_t timeout_sec,
int timeout_nsec) {
1416 remove_timeout_timer(node);
1418 if (timeout_sec <= 0 && timeout_nsec <= 0) {
1422 if (!node.task_.get_context()) {
1427 timer_node.
task_id = node.task_.get_id();
1431 std::pair<typename std::set<detail::task_timer_node<id_type>>::iterator,
bool> res =
1432 task_timeout_timer_.insert(timer_node);
1434 node.timer_node = res.first;
1438 void remove_timeout_timer(detail::task_manager_node<task_type> &node) {
1439 if (node.timer_node != task_timeout_timer_.end()) {
1440 task_timeout_timer_.erase(node.timer_node);
1441 node.timer_node = task_timeout_timer_.end();
1445 # if defined(LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER) && LIBCOTASK_MACRO_AUTO_CLEANUP_MANAGER
1446 static void task_cleanup_callback(
void *self_ptr, task_context_base<TVALUE> &task_inst) {
1447 if (
nullptr == self_ptr) {
1451 reinterpret_cast<self_type *
>(self_ptr)->remove_task(task_inst.get_id(), &task_inst);
1456 container_type tasks_;
1458 std::set<detail::task_timer_node<id_type>> task_timeout_timer_;
1460 # if !defined(LIBCOPP_DISABLE_ATOMIC_LOCK) || !(LIBCOPP_DISABLE_ATOMIC_LOCK)
1461 LIBCOPP_COPP_NAMESPACE_ID::util::lock::spin_lock action_lock_;
1467 LIBCOPP_COTASK_NAMESPACE_END
LIBCOPP_COTASK_API bool is_exiting() const LIBCOPP_MACRO_NOEXCEPT
check if a cotask is exiting
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)
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
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
LIBCOPP_COPP_NAMESPACE_ID::util::lock::spin_lock action_lock_
std::shared_ptr< self_type > ptr_type
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_
const container_type & get_container() const LIBCOPP_MACRO_NOEXCEPT
task container, this api is just used for provide information to users
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)
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
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::util::intrusive_ptr< self_type > ptr_type
@ COPP_EC_EXTERNAL_INSERT_FAILED
COPP_EC_EXTERNAL_INSERT_FAILED.
@ COPP_EC_IN_RESET
COPP_EC_IN_RESET.
@ COPP_EC_CAST_FAILED
COPP_EC_CAST_FAILED.
@ COPP_EC_SUCCESS
COPP_EC_SUCCESS.
@ COPP_EC_NOT_FOUND
COPP_EC_NOT_FOUND.
@ COPP_EC_TASK_IS_EXITING
COPP_EC_TASK_IS_EXITING.
@ COPP_EC_ALREADY_EXIST
COPP_EC_ALREADY_EXIST.
@ COPP_EC_TASK_ALREADY_IN_ANOTHER_MANAGER
COPP_EC_TASK_ALREADY_IN_ANOTHER_MANAGER.
@ COPP_EC_ARGS_ERROR
COPP_EC_ARGS_ERROR.
struct LIBCOPP_COTASK_API_HEAD_ONLY task_manager_node
std::shared_ptr< cli::cmd_option_value > value_type
my_task_t::ptr_t task_ptr_type
std::set< task_timer_node< typename task< TCO_MACRO >::id_type > >::iterator timer_node
typename task< TCO_MACRO >::ptr_type task_ptr_type
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