docs/task__group_8hpp_source.html
| | Taskflow: A General-purpose Task-parallel Programming System |
Loading...
Searching...
No Matches
task_group.hpp
1#pragma once
2
3#include "executor.hpp"
4
5namespace tf {
6
7// ------------------------------------------------------------------------------------------------
8// class: TaskGroup
9// ------------------------------------------------------------------------------------------------
10
62
63friend class Executor;
64
65public:
66
67// ----------------------------------------------------------------------------------------------
68// deleted members
69// ----------------------------------------------------------------------------------------------
70
74TaskGroup(const TaskGroup&) = delete;
75
79TaskGroup(TaskGroup&&) = delete;
80
84TaskGroup& operator =(TaskGroup&&) = delete;
85
89TaskGroup& operator =(const TaskGroup&) = delete;
90
103 Executor& executor();
104
105// ----------------------------------------------------------------------------------------------
106// async methods
107// ----------------------------------------------------------------------------------------------
108
141template <typename F>
142auto async(F&& f);
143
165template <typename P, typename F>
166auto async(P&& params, F&& f);
167
168// ----------------------------------------------------------------------------------------------
169// silent async methods
170// ----------------------------------------------------------------------------------------------
171
194template <typename F>
195void silent_async(F&& f);
196
215template <typename P, typename F>
216void silent_async(P&& params, F&& f);
217
218// ----------------------------------------------------------------------------------------------
219// dependent async methods
220// ----------------------------------------------------------------------------------------------
221
257template <typename F, typename... Tasks>
258requires (std::same_as<std::decay_t<Tasks>, AsyncTask> && ...)
259auto dependent_async(F&& func, Tasks&&... tasks);
260
300template <TaskParamsLike P, typename F, typename... Tasks>
301requires (std::same_as<std::decay_t<Tasks>, AsyncTask> && ...)
302auto dependent_async(P&& params, F&& func, Tasks&&... tasks);
303
342template <typename F, typename I>
343requires (!std::same_as<std::decay_t<I>, AsyncTask>)
344auto dependent_async(F&& func, I first, I last);
345
388template <TaskParamsLike P, typename F, typename I>
389requires (!std::same_as<std::decay_t<I>, AsyncTask>)
390auto dependent_async(P&& params, F&& func, I first, I last);
391
392
393// ----------------------------------------------------------------------------------------------
394// silent dependent async methods
395// ----------------------------------------------------------------------------------------------
396
425template <typename F, typename... Tasks>
426requires (std::same_as<std::decay_t<Tasks>, AsyncTask> && ...)
427tf::AsyncTask silent_dependent_async(F&& func, Tasks&&... tasks);
428
461template <TaskParamsLike P, typename F, typename... Tasks>
462requires (std::same_as<std::decay_t<Tasks>, AsyncTask> && ...)
463tf::AsyncTask silent_dependent_async(P&& params, F&& func, Tasks&&... tasks);
464
498template <typename F, typename I>
499requires (!std::same_as<std::decay_t<I>, AsyncTask>)
500tf::AsyncTask silent_dependent_async(F&& func, I first, I last);
501
537template <TaskParamsLike P, typename F, typename I>
538requires (!std::same_as<std::decay_t<I>, AsyncTask>)
539tf::AsyncTask silent_dependent_async(P&& params, F&& func, I first, I last);
540
541
542// ----------------------------------------------------------------------------------------------
543// cooperative execution methods
544// ----------------------------------------------------------------------------------------------
545
578void corun();
579
636void cancel();
637
661bool is_cancelled();
662
687size_t size() const;
688
689private:
690
694explicit TaskGroup(Executor&, Worker&);
695
699 Executor& _executor;
700
704Worker& _worker;
705
709 NodeBase _node_base;
710};
711
712// constructor
713inline TaskGroup::TaskGroup(Executor& executor, Worker& worker) :
714 _executor {executor},
715 _worker {worker},
716 _node_base {NSTATE::IMPLICITLY_ANCHORED, ESTATE::NONE, nullptr, 0} {
717}
718
719// Function: executor
720inline Executor& TaskGroup::executor() {
721return _executor;
722}
723
724// Function: corun
725inline void TaskGroup::corun() {
726 {
727 ExplicitAnchorGuard anchor(&_node_base);
728 _executor._corun_until(_worker, [this] () -> bool {
729return _node_base._join_counter.load(std::memory_order_acquire) == 0;
730 });
731 }
732 _node_base._rethrow_exception();
733}
734
735// Function: cancel
736inline void TaskGroup::cancel() {
737 _node_base._estate.fetch_or(ESTATE::CANCELLED, std::memory_order_relaxed);
738}
739
740// Function: is_cancelled
741inline bool TaskGroup::is_cancelled() {
742return _node_base._estate.load(std::memory_order_relaxed) & ESTATE::CANCELLED;
743}
744
745// Function: size
746inline size_t TaskGroup::size() const {
747return _node_base._join_counter.load(std::memory_order_relaxed);
748}
749
750// ------------------------------------------------------------------------------------------------
751// TaskGroup::silent_async
752// ------------------------------------------------------------------------------------------------
753
754// Function: silent_async
755template <typename F>
756void TaskGroup::silent_async(F&& f) {
757silent_async(DefaultTaskParams{}, std::forward<F>(f));
758}
759
760// Function: silent_async
761template <typename P, typename F>
762void TaskGroup::silent_async(P&& params, F&& f) {
763 _node_base._join_counter.fetch_add(1, std::memory_order_relaxed);
764 _executor._silent_async(
765 std::forward<P>(params), std::forward<F>(f), nullptr, &_node_base
766 );
767}
768
769// ------------------------------------------------------------------------------------------------
770// TaskGroup::async
771// ------------------------------------------------------------------------------------------------
772
773// Function: async
774template <typename F>
775auto TaskGroup::async(F&& f) {
776return async(DefaultTaskParams{}, std::forward<F>(f));
777}
778
779// Function: async
780template <typename P, typename F>
781auto TaskGroup::async(P&& params, F&& f) {
782 _node_base._join_counter.fetch_add(1, std::memory_order_relaxed);
783return _executor._async(
784 std::forward<P>(params), std::forward<F>(f), nullptr, &_node_base
785 );
786}
787
788// ------------------------------------------------------------------------------------------------
789// silent dependent async
790// ------------------------------------------------------------------------------------------------
791
792// Function: silent_dependent_async
793template <typename F, typename... Tasks>
794requires (std::same_as<std::decay_t<Tasks>, AsyncTask> && ...)
795tf::AsyncTask TaskGroup::silent_dependent_async(F&& func, Tasks&&... tasks) {
796return silent_dependent_async(
797DefaultTaskParams{}, std::forward<F>(func), std::forward<Tasks>(tasks)...
798 );
799}
800
801// Function: silent_dependent_async
802template <TaskParamsLike P, typename F, typename... Tasks>
803requires (std::same_as<std::decay_t<Tasks>, AsyncTask> && ...)
804tf::AsyncTask TaskGroup::silent_dependent_async(
805 P&& params, F&& func, Tasks&&... tasks
806){
807 std::array<AsyncTask, sizeof...(Tasks)> array = { std::forward<Tasks>(tasks)... };
808return silent_dependent_async(
809 std::forward<P>(params), std::forward<F>(func), array.begin(), array.end()
810 );
811}
812
813// Function: silent_dependent_async
814template <typename F, typename I>
815requires (!std::same_as<std::decay_t<I>, AsyncTask>)
816tf::AsyncTask TaskGroup::silent_dependent_async(F&& func, I first, I last) {
817return silent_dependent_async(DefaultTaskParams{}, std::forward<F>(func), first, last);
818}
819
820// Function: silent_dependent_async
821template <TaskParamsLike P, typename F, typename I>
822requires (!std::same_as<std::decay_t<I>, AsyncTask>)
823tf::AsyncTask TaskGroup::silent_dependent_async(
824 P&& params, F&& func, I first, I last
826 _node_base._join_counter.fetch_add(1, std::memory_order_relaxed);
827return _executor._silent_dependent_async(
828 std::forward<P>(params), std::forward<F>(func), first, last, nullptr, &_node_base
829 );
830}
831
832// ------------------------------------------------------------------------------------------------
833// dependent async
834// ------------------------------------------------------------------------------------------------
835
836// Function: dependent_async
837template <typename F, typename... Tasks>
838requires (std::same_as<std::decay_t<Tasks>, AsyncTask> && ...)
839auto TaskGroup::dependent_async(F&& func, Tasks&&... tasks) {
840return dependent_async(DefaultTaskParams{}, std::forward<F>(func), std::forward<Tasks>(tasks)...);
841}
842
843// Function: dependent_async
844template <TaskParamsLike P, typename F, typename... Tasks>
845requires (std::same_as<std::decay_t<Tasks>, AsyncTask> && ...)
846auto TaskGroup::dependent_async(P&& params, F&& func, Tasks&&... tasks) {
847 std::array<AsyncTask, sizeof...(Tasks)> array = { std::forward<Tasks>(tasks)... };
848return dependent_async(
849 std::forward<P>(params), std::forward<F>(func), array.begin(), array.end()
850 );
851}
852
853// Function: dependent_async
854template <typename F, typename I>
855requires (!std::same_as<std::decay_t<I>, AsyncTask>)
856auto TaskGroup::dependent_async(F&& func, I first, I last) {
857return dependent_async(DefaultTaskParams{}, std::forward<F>(func), first, last);
858}
859
860// Function: dependent_async
861template <TaskParamsLike P, typename F, typename I>
862requires (!std::same_as<std::decay_t<I>, AsyncTask>)
863auto TaskGroup::dependent_async(P&& params, F&& func, I first, I last) {
864 _node_base._join_counter.fetch_add(1, std::memory_order_relaxed);
865return _executor._dependent_async(
866 std::forward<P>(params), std::forward<F>(func), first, last, nullptr, &_node_base
867 );
868}
869
870// ----------------------------------------------------------------------------
871// Executor Forward Declaration
872// ----------------------------------------------------------------------------
873
874// Procedure: task_group
875inline TaskGroup Executor::task_group() {
876Worker* w = this_worker();
877if(w == nullptr) {
878 TF_THROW("task_group can only created by a worker of the executor");
879 }
880return TaskGroup(*this, *w);
881}
882
883
884} // end of namespace tf -----------------------------------------------------
class to hold a dependent asynchronous task with shared ownership
Definition async_task.hpp:45
class to create an empty task parameter for compile-time optimization
Definition graph.hpp:191
class to create an executor
Definition executor.hpp:62
TaskGroup task_group()
creates a task group that executes a collection of asynchronous tasks
Definition task_group.hpp:875
Worker * this_worker()
queries pointer to the calling worker if it belongs to this executor, otherwise returns nullptr
void corun()
corun all tasks spawned by this task group with other workers
Definition task_group.hpp:725
void cancel()
cancel all tasks in this task group
Definition task_group.hpp:736
size_t size() const
queries the number of tasks currently in this task group
Definition task_group.hpp:746
tf::TaskGroup::silent_dependent_async
tf::AsyncTask silent_dependent_async(F &&func, Tasks &&... tasks)
runs the given function asynchronously when the given predecessors finish
Definition task_group.hpp:795
auto async(F &&f)
runs the given callable asynchronously
Definition task_group.hpp:775
TaskGroup & operator=(TaskGroup &&)=delete
disabled copy assignment
bool is_cancelled()
queries if the task group has been cancelled
Definition task_group.hpp:741
TaskGroup(TaskGroup &&)=delete
disabled move constructor
tf::TaskGroup::dependent_async
auto dependent_async(F &&func, Tasks &&... tasks)
runs the given function asynchronously when the given predecessors finish
Definition task_group.hpp:839
TaskGroup(const TaskGroup &)=delete
disabled copy constructor
Executor & executor()
obtains the executor that creates this task group
Definition task_group.hpp:720
void silent_async(F &&f)
runs the given function asynchronously without returning any future object
Definition task_group.hpp:756
class to create a worker in an executor
Definition worker.hpp:55
determines if a type is a task parameter type
Definition graph.hpp:202
taskflow namespace
Definition small_vector.hpp:20