# Taskflow Algorithms » Module Algorithm

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 Header

You 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 Task

Similar 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::Executor executor;

    tf::Taskflow A;
    tf::Taskflow B;
    tf::Taskflow C;
    tf::Taskflow D;

    A.emplace([](){ printf("Taskflow A\n"); });
    B.emplace([](){ printf("Taskflow B\n"); });
    C.emplace([](){ printf("Taskflow C\n"); });
    D.emplace([](){ printf("Taskflow D\n"); });

    // launch the four taskflows using asynchronous tasking
    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:

    {.shell-session}
    # one possible output
    Taskflow B
    Taskflow C
    Taskflow A
    Taskflow D

    # another possible output
    Taskflow D
    Taskflow A
    Taskflow B
    Taskflow C

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::Executor executor;

    tf::Taskflow A;
    tf::Taskflow B;
    tf::Taskflow C;
    tf::Taskflow D;

    A.emplace([](){ printf("Taskflow A\n"); });
    B.emplace([](){ printf("Taskflow B\n"); });
    C.emplace([](){ printf("Taskflow C\n"); });
    D.emplace([](){ printf("Taskflow D\n"); });

    auto TA = executor.silent_dependent_async(tf::make_module_task(A));
    auto TB = executor.silent_dependent_async(tf::make_module_task(B), TA);
    auto TC = executor.silent_dependent_async(tf::make_module_task(C), TB);
    auto [TD, FD] = executor.dependent_async(tf::make_module_task(D), TC);
    FD.get();

    {.shell-session}
    # dependent-async tasks enforce a sequential execution of the four taskflows
    Taskflow A
    Taskflow B
    Taskflow C
    Taskflow D

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.

    // approach 1: composition using composed_of
    tf::Task m1 = taskflow1.composed_of(taskflow2);

    // approach 2: composition using make_module_task
    tf::Task m1 = taskflow1.emplace(tf::make_module_task(taskflow2));

#### Attention

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 Graph

In 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:

    struct CustomGraph {
      tf::Graph graph;
      CustomGraph() {
        // use flow builder to inherit all task creation methods in tf::Taskflow
        tf::FlowBuilder builder(graph);
        tf::Task task = builder.emplace([](){
          std::cout << "a task\n";  // static task
        });
      }
      // returns a reference to the graph for taskflow composition
      Graph& graph() { return graph; }
    };

    CustomGraph target;
    executor.async(tf::make_module_task(target));

#### Attention

Users are responsible for ensuring the given custom graph remains valid throughout its execution. The executor does not assume ownership of the custom graph.

Tab / T to search, Esc to close
…

Search for symbols, directories, files, pages or modules. You can omit any prefix from the symbol or file path; adding a `:` or `/` suffix lists all members of given symbol or directory.

Use ↓ / ↑ to navigate through the list, Enter to go. Tab autocompletes common prefix, you can copy a link to the result using ⌘ L while ⌘ M produces a Markdown link.

Sorry, nothing was found.