4 #include "fly/task/types.hpp"
12 #include <type_traits>
18 fly::task::TaskLocation({__FILE__, __FUNCTION__, static_cast<std::uint32_t>(__LINE__)})
112 class TaskRunner :
public std::enable_shared_from_this<TaskRunner>
132 template <
typename TaskType>
150 template <
typename OwnerType,
typename TaskType>
169 template <
typename TaskType,
typename ReplyType>
195 template <
typename OwnerType,
typename TaskType,
typename ReplyType>
198 std::weak_ptr<OwnerType> weak_owner,
213 template <
typename TaskType>
233 template <
typename OwnerType,
typename TaskType>
236 std::weak_ptr<OwnerType> weak_owner,
237 std::chrono::milliseconds delay,
257 template <
typename TaskType,
typename ReplyType>
260 std::chrono::milliseconds delay,
288 template <
typename OwnerType,
typename TaskType,
typename ReplyType>
291 std::weak_ptr<OwnerType> weak_owner,
292 std::chrono::milliseconds delay,
302 TaskRunner(std::shared_ptr<TaskManager> task_manager) noexcept;
344 std::chrono::milliseconds delay,
351 template <
typename TaskType>
366 template <
typename TaskType>
367 Task wrap_task(TaskType &&task);
382 template <
typename OwnerType,
typename TaskType>
383 Task wrap_task(std::weak_ptr<OwnerType> weak_owner, TaskType &&task);
399 template <
typename TaskType,
typename ReplyType>
400 Task wrap_task(TaskType &&task, ReplyType &&reply);
421 template <
typename OwnerType,
typename TaskType,
typename ReplyType>
422 Task wrap_task(std::weak_ptr<OwnerType> weak_owner, TaskType &&task, ReplyType &&reply);
432 std::weak_ptr<TaskManager> m_weak_task_manager;
452 static std::shared_ptr<ParallelTaskRunner>
create(std::shared_ptr<TaskManager> task_manager);
497 static std::shared_ptr<SequencedTaskRunner>
create(std::shared_ptr<TaskManager> task_manager);
541 bool maybe_post_task(
TaskLocation &&location, Task &&task);
543 std::mutex m_pending_tasks_mutex;
544 std::queue<PendingTask> m_pending_tasks;
545 bool m_has_running_task {
false};
549 template <
typename TaskType>
552 return post_task_internal(std::move(location), wrap_task(std::forward<TaskType>(task)));
556 template <
typename OwnerType,
typename TaskType>
559 std::weak_ptr<OwnerType> weak_owner,
564 wrap_task(std::move(weak_owner), std::forward<TaskType>(task)));
568 template <
typename TaskType,
typename ReplyType>
573 wrap_task(std::forward<TaskType>(task), std::forward<ReplyType>(reply)));
577 template <
typename OwnerType,
typename TaskType,
typename ReplyType>
580 std::weak_ptr<OwnerType> weak_owner,
587 std::move(weak_owner),
588 std::forward<TaskType>(task),
589 std::forward<ReplyType>(reply)));
593 template <
typename TaskType>
596 std::chrono::milliseconds delay,
602 wrap_task(std::forward<TaskType>(task)));
606 template <
typename OwnerType,
typename TaskType>
609 std::weak_ptr<OwnerType> weak_owner,
610 std::chrono::milliseconds delay,
616 wrap_task(std::move(weak_owner), std::forward<TaskType>(task)));
620 template <
typename TaskType,
typename ReplyType>
623 std::chrono::milliseconds delay,
630 wrap_task(std::forward<TaskType>(task), std::forward<ReplyType>(reply)));
634 template <
typename OwnerType,
typename TaskType,
typename ReplyType>
637 std::weak_ptr<OwnerType> weak_owner,
638 std::chrono::milliseconds delay,
645 wrap_task(std::move(weak_owner), std::forward<TaskType>(task), std::move(reply)));
649 template <
typename TaskType>
650 Task TaskRunner::wrap_task(TaskType &&task)
652 static_assert(std::is_invocable_v<TaskType>,
"Task must be invocable without any arguments");
654 TaskHolder<TaskType> holder {std::forward<TaskType>(task)};
656 return [holder = std::move(holder)](
TaskRunner *, TaskLocation)
mutable {
657 FLY_UNUSED(std::invoke(std::move(holder.m_task)));
662 template <
typename OwnerType,
typename TaskType>
663 Task TaskRunner::wrap_task(std::weak_ptr<OwnerType> weak_owner, TaskType &&task)
665 using StrongOwnerType = std::shared_ptr<OwnerType>;
668 std::is_invocable_v<TaskType, StrongOwnerType>,
669 "Task must be invocable with only a strong pointer to its owner");
671 TaskHolder<TaskType> holder {std::forward<TaskType>(task)};
673 return [weak_owner = std::move(weak_owner),
674 holder = std::move(holder)](
TaskRunner *, TaskLocation)
mutable {
675 if (StrongOwnerType owner = weak_owner.lock(); owner)
677 FLY_UNUSED(std::invoke(std::move(holder.m_task), std::move(owner)));
683 template <
typename TaskType,
typename ReplyType>
684 Task TaskRunner::wrap_task(TaskType &&task, ReplyType &&reply)
686 static_assert(std::is_invocable_v<TaskType>,
"Task must be invocable without any arguments");
688 using ResultType = std::invoke_result_t<TaskType>;
689 static constexpr
bool s_result_is_void = std::is_void_v<ResultType>;
692 (s_result_is_void && std::is_invocable_v<ReplyType>) ||
693 (!s_result_is_void && std::is_invocable_v<ReplyType, ResultType>),
694 "Either the task must return a non-void type and the reply must be invocable with only "
695 "that type, or the task must return void and the reply must be invocable without any "
698 TaskHolder<TaskType> task_holder {std::forward<TaskType>(task)};
699 TaskHolder<ReplyType> reply_holder {std::forward<ReplyType>(reply)};
701 return [task_holder = std::move(task_holder),
703 std::move(reply_holder)](
TaskRunner *runner, TaskLocation location)
mutable {
704 if constexpr (s_result_is_void)
706 std::invoke(std::move(task_holder.m_task));
707 runner->post_task(std::move(location), std::move(reply_holder.m_task));
711 auto result = std::invoke(std::move(task_holder.m_task));
715 std::bind(std::move(reply_holder.m_task), std::move(result)));
721 template <
typename OwnerType,
typename TaskType,
typename ReplyType>
722 Task TaskRunner::wrap_task(std::weak_ptr<OwnerType> weak_owner, TaskType &&task, ReplyType &&reply)
724 using StrongOwnerType = std::shared_ptr<OwnerType>;
727 std::is_invocable_v<TaskType, StrongOwnerType>,
728 "Task must be invocable with only a strong pointer to its owner");
730 using ResultType = std::invoke_result_t<TaskType, StrongOwnerType>;
731 static constexpr
bool s_result_is_void = std::is_void_v<ResultType>;
734 (s_result_is_void && std::is_invocable_v<ReplyType, StrongOwnerType>) ||
735 (!s_result_is_void && std::is_invocable_v<ReplyType, ResultType, StrongOwnerType>),
736 "Either the task must return a non-void type and the reply must be invocable with that "
737 "type and a strong pointer to its owner, or the task must return void and the reply must "
738 "be invocable with only a strong pointer to its owner");
740 TaskHolder<TaskType> task_holder {std::forward<TaskType>(task)};
741 TaskHolder<ReplyType> reply_holder {std::forward<ReplyType>(reply)};
743 return [weak_owner = std::move(weak_owner),
744 task_holder = std::move(task_holder),
746 std::move(reply_holder)](
TaskRunner *runner, TaskLocation location)
mutable {
747 if (StrongOwnerType owner = weak_owner.lock(); owner)
749 if constexpr (s_result_is_void)
751 std::invoke(std::move(task_holder.m_task), std::move(owner));
755 std::move(weak_owner),
756 std::move(reply_holder.m_task));
760 auto result = std::invoke(std::move(task_holder.m_task), std::move(owner));
764 std::move(weak_owner),
766 std::move(reply_holder.m_task),
768 std::placeholders::_1));
Definition: task_runner.hpp:443
bool post_task_internal(TaskLocation &&location, Task &&task) override
Definition: task_runner.cpp:76
void task_complete(TaskLocation &&location) override
Definition: task_runner.cpp:82
static std::shared_ptr< ParallelTaskRunner > create(std::shared_ptr< TaskManager > task_manager)
Definition: task_runner.cpp:54
Definition: task_runner.hpp:488
bool post_task_internal(TaskLocation &&location, Task &&task) override
Definition: task_runner.cpp:110
void task_complete(TaskLocation &&location) override
Definition: task_runner.cpp:116
static std::shared_ptr< SequencedTaskRunner > create(std::shared_ptr< TaskManager > task_manager)
Definition: task_runner.cpp:88
Definition: task_manager.hpp:30
Definition: task_runner.hpp:113
bool post_task_with_delay(TaskLocation &&location, std::chrono::milliseconds delay, TaskType &&task)
Definition: task_runner.hpp:594
TaskRunner(std::shared_ptr< TaskManager > task_manager) noexcept
Definition: task_runner.cpp:8
bool post_task_to_task_manager(TaskLocation &&location, Task &&task)
Definition: task_runner.cpp:14
virtual void task_complete(TaskLocation &&location)=0
bool post_task_with_delay_and_reply(TaskLocation &&location, std::chrono::milliseconds delay, TaskType &&task, ReplyType &&reply)
Definition: task_runner.hpp:621
bool post_task_to_task_manager_with_delay(TaskLocation &&location, std::chrono::milliseconds delay, Task &&task)
Definition: task_runner.cpp:26
bool post_task(TaskLocation &&location, TaskType &&task)
Definition: task_runner.hpp:550
virtual ~TaskRunner()=default
virtual bool post_task_internal(TaskLocation &&location, Task &&task)=0
bool post_task_with_reply(TaskLocation &&location, TaskType &&task, ReplyType &&reply)
Definition: task_runner.hpp:569