ModuleAlgorithm Module Algorithm Include the Header ModuleAlgorithm_1ModuleAlgorithmInclude What is a Module Task ModuleAlgorithm_1WhatIsAModuleTask Create a Module Task over a Custom Graph ModuleAlgorithm_1CreateAModuleTaskOverACustomGraph Taskflow provides template methods that let users create reusable building blocks called modules. Users can connect modules together to build more complex parallel algorithms. Include the HeaderYou need to include the header file, taskflow/algorithm/module.hpp, for creating a module task over a schedulable graph target. #include<taskflow/algorithm/module.hpp> What is a Module TaskSimilar to Composable Tasking, but in a more generic setting, the template function, tf::make_module_task, allows you to create a task over a taskflow graph that can be executed by an executor. This provides a flexible way to encapsulate and reuse complex task logic within your Taskflow applications. The example below demonstrates how to create and launch multiple taskflows in parallel using asynchronous tasking: tf::Executorexecutor; tf::TaskflowA; tf::TaskflowB; tf::TaskflowC; tf::TaskflowD; A.emplace([](){printf("TaskflowA\n");}); B.emplace([](){printf("TaskflowB\n");}); C.emplace([](){printf("TaskflowC\n");}); D.emplace([](){printf("TaskflowD\n");}); //launchthefourtaskflowsusingasynchronoustasking executor.async(tf::make_module_task(A)); executor.async(tf::make_module_task(B)); executor.async(tf::make_module_task(C)); executor.async(tf::make_module_task(D)); executor.wait_for_all(); Since the four taskflows are launched asynchronously without any dependencies between them, we can observe any order of the output message: #onepossibleoutput TaskflowB TaskflowC TaskflowA TaskflowD #anotherpossibleoutput TaskflowD TaskflowA TaskflowB TaskflowC If you need to enforce dependencies among these four taskflows, you can use dependent-async tasks. The example below launches the four taskflows one by one in sequential: tf::Executorexecutor; tf::TaskflowA; tf::TaskflowB; tf::TaskflowC; tf::TaskflowD; A.emplace([](){printf("TaskflowA\n");}); B.emplace([](){printf("TaskflowB\n");}); C.emplace([](){printf("TaskflowC\n");}); D.emplace([](){printf("TaskflowD\n");}); autoTA=executor.silent_dependent_async(tf::make_module_task(A)); autoTB=executor.silent_dependent_async(tf::make_module_task(B),TA); autoTC=executor.silent_dependent_async(tf::make_module_task(C),TB); auto[TD,FD]=executor.dependent_async(tf::make_module_task(D),TC); FD.get(); #dependent-asynctasksenforceasequentialexecutionofthefourtaskflows TaskflowA TaskflowB TaskflowC TaskflowD The module task maker, tf::make_module_task, functions basically similar to tf::Taskflow::composed_of but provides a more generic interface that can be used beyond Taskflow. Specifically, the following two approaches achieve the same functionality. //approach1:compositionusingcomposed_of tf::Taskm1=taskflow1.composed_of(taskflow2); //approach2:compositionusingmake_module_task tf::Taskm1=taskflow1.emplace(tf::make_module_task(taskflow2)); Similar to tf::Taskflow::composed_of, tf::make_module_task does not assume ownership of the provided taskflow but a soft reference. You are responsible for ensuring that the encapsulated taskflow remains valid throughout its execution. Create a Module Task over a Custom GraphIn addition to encapsulate taskflow graphs, you can create a module task to schedule a custom graph target. A schedulable target (of type T) must define the method T::graph() that returns a reference to the tf::Graph object managed by T. The following example defines a custom graph that can be scheduled through making module tasks: structCustomGraph{ tf::Graphgraph; CustomGraph(){ //useflowbuildertoinheritalltaskcreationmethodsintf::Taskflow tf::FlowBuilderbuilder(graph); tf::Tasktask=builder.emplace([](){ std::cout<<"atask\n";//statictask }); } //returnsareferencetothegraphfortaskflowcomposition Graph&graph(){returngraph;} }; CustomGraphtarget; executor.async(tf::make_module_task(target)); Users are responsible for ensuring the given custom graph remains valid throughout its execution. The executor does not assume ownership of the custom graph.