<!-- iframe showing the search results (closed by default) -->
<divid="MSearchResultsWindow">
<iframesrc="javascript:void(0)" frameborder="0"
name="MSearchResults" id="MSearchResults">
</iframe>
</div>
<divclass="header">
<divclass="headertitle">
<divclass="title">C2: Dispatch a Task Dependency Graph </div></div>
</div><!--header-->
<divclass="contents">
<divclass="textblock"><p>After you create a task dependency graph, you need to dispatch it to threads for execution. In this chapter, we will show you how to execute a task dependency graph.</p>
<h1><aclass="anchor" id="GraphAndTopology"></a>
Graph and Topology</h1>
<p>Each taskflow object has exactly one graph at a time that represents the tasks and the dependencies constructed so far. The graph exists until users dispatch it for execution. In Cpp-Taskflow, we call a dispatched graph a <em>topology</em>. A topology is a data structure that wraps up a dispatched graph and stores a few metadata obtained at runtime. Each taskflow object has a list of topologies to keep track of the execution status of dispatched graphs. Users can retrieve this information later on for graph inspection and debugging.</p>
<p>All tasks are executed in a shared thread storage coupled with a <em>task scheduler</em> to decide which thread runs which task. Cpp-Taskflow provides two ways to dispatch a task dependency graph, <em>blocking</em> and <em>non-blocking</em> executions.</p>
<h1><aclass="anchor" id="BlockingExecution"></a>
Blocking Execution</h1>
<p>One way to dispatch the present task dependency graph is to use the method <aclass="el" href="classtf_1_1BasicTaskflow.html#a37ef86998f23ee7315be032c40fe815e" title="dispatches the present graph to threads and wait for all topologies to complete ">tf::Taskflow::wait_for_all</a>. Calling <code>wait_for_all</code> dispatches the graph to threads and blocks the program flow until all tasks finish.</p>
<divclass="fragment"><divclass="line"><aclass="code" href="classtf_1_1BasicTaskflow.html">tf::Taskflow</a> taskflow;</div><divclass="line"></div><divclass="line"><aclass="code" href="classtf_1_1Task.html">tf::Task</a> A = taskflow.<aclass="code" href="classtf_1_1FlowBuilder.html#a4d52a7fe2814b264846a2085e931652c">emplace</a>([] () { <aclass="codeRef" doxygen="/Users/twhuang/PhD/Code/cpp-taskflow/docs/cppreference-doxygen-web.tag.xml:http://en.cppreference.com/w/" href="http://en.cppreference.com/w/cpp/io/basic_ostream.html">std::cout</a> << <spanclass="stringliteral">"TaskA\n"</span>; });</div><divclass="line"><aclass="code" href="classtf_1_1Task.html">tf::Task</a> B = taskflow.<aclass="code" href="classtf_1_1FlowBuilder.html#a4d52a7fe2814b264846a2085e931652c">emplace</a>([] () { <aclass="codeRef" doxygen="/Users/twhuang/PhD/Code/cpp-taskflow/docs/cppreference-doxygen-web.tag.xml:http://en.cppreference.com/w/" href="http://en.cppreference.com/w/cpp/io/basic_ostream.html">std::cout</a> << <spanclass="stringliteral">"TaskB\n"</span>; });</div><divclass="line">A.<aclass="code" href="classtf_1_1Task.html#a8c78c453295a553c1c016e4062da8588">precede</a>(B);</div><divclass="line"></div><divclass="line">taskflow.<aclass="code" href="classtf_1_1BasicTaskflow.html#a37ef86998f23ee7315be032c40fe815e">wait_for_all</a>();</div></div><!-- fragment --><p>When <code>wait_for_all</code> returns, all tasks including previously dispatched ones are guaranteed to finish. All topologies will be cleaned up as well.</p>
<p>Another way to dispatch the present task dependency graph is to use the method <aclass="el" href="classtf_1_1BasicTaskflow.html#a848e425f67b49a8a7ac21f6b791999c5" title="dispatches the present graph to threads and returns immediately ">tf::Taskflow::dispatch</a> or <aclass="el" href="classtf_1_1BasicTaskflow.html#a0126001a2bd8603af4827049578629cb" title="dispatches the present graph to threads and returns immediately ">tf::Taskflow::silent_dispatch</a>. These two methods both dispatch the present graph to threads and return immediately without blocking the program flow. Non-blocking methods allow the program to perform other computations that can overlap the graph execution.</p>
<divclass="fragment"><divclass="line"> 1: <aclass="code" href="classtf_1_1BasicTaskflow.html">tf::Taskflow</a> taskflow;</div><divclass="line"> 2:</div><divclass="line"> 3: <aclass="code" href="classtf_1_1Task.html">tf::Task</a> A = taskflow.<aclass="code" href="classtf_1_1FlowBuilder.html#a4d52a7fe2814b264846a2085e931652c">emplace</a>([] () { <aclass="codeRef" doxygen="/Users/twhuang/PhD/Code/cpp-taskflow/docs/cppreference-doxygen-web.tag.xml:http://en.cppreference.com/w/" href="http://en.cppreference.com/w/cpp/io/basic_ostream.html">std::cout</a> << <spanclass="stringliteral">"Task A\n"</span>; });</div><divclass="line"> 4: <aclass="code" href="classtf_1_1Task.html">tf::Task</a> B = taskflow.<aclass="code" href="classtf_1_1FlowBuilder.html#a4d52a7fe2814b264846a2085e931652c">emplace</a>([] () { <aclass="codeRef" doxygen="/Users/twhuang/PhD/Code/cpp-taskflow/docs/cppreference-doxygen-web.tag.xml:http://en.cppreference.com/w/" href="http://en.cppreference.com/w/cpp/io/basic_ostream.html">std::cout</a> << <spanclass="stringliteral">"Task B\n"</span>; });</div><divclass="line"> 5: A.<aclass="code" href="classtf_1_1Task.html#a8c78c453295a553c1c016e4062da8588">precede</a>(B);</div><divclass="line"> 6:</div><divclass="line"> 7: <spanclass="keyword">auto</span> F = taskflow.<aclass="code" href="classtf_1_1BasicTaskflow.html#a848e425f67b49a8a7ac21f6b791999c5">dispatch</a>();</div><divclass="line"> 8: <spanclass="comment">// do some computation to overlap the execution of tasks A and B</span></div><divclass="line"> 9: <spanclass="comment">// ...</span></div><divclass="line">10: F.get();</div></div><!-- fragment --><p>Debrief:</p>
<ul>
<li>Line 1-5 creates a graph with two tasks and one dependency </li>
<li>Line 7 dispatches this graph </li>
<li>and obtains a <aclass="elRef" doxygen="/Users/twhuang/PhD/Code/cpp-taskflow/docs/cppreference-doxygen-web.tag.xml:http://en.cppreference.com/w/" href="http://en.cppreference.com/w/cpp/thread/shared_future.html">std::shared_future</a> object to access its execution status </li>
<li>Line 8-9 performs some computations to overlap the execution of task A and task B </li>
<li>Line 10 blocks the program until this topology finishes</li>
</ul>
<p>The method <code>dispatch</code> has a overload that takes a callable object to execute when the dispatched graph finishes.</p>
<divclass="fragment"><divclass="line"><aclass="code" href="classtf_1_1BasicTaskflow.html">tf::Taskflow</a> taskflow;</div><divclass="line"><spanclass="keywordtype">int</span> counter {0};</div><divclass="line"><aclass="code" href="classtf_1_1Task.html">tf::Task</a> A = taskflow.<aclass="code" href="classtf_1_1FlowBuilder.html#a4d52a7fe2814b264846a2085e931652c">emplace</a>([&] () { counter++; });</div><divclass="line">taskflow.<aclass="code" href="classtf_1_1BasicTaskflow.html#a848e425f67b49a8a7ac21f6b791999c5">dispatch</a>([&] () { assert(counter == 1); })</div></div><!-- fragment --><p>If you do not care the status of a dispatched graph, use the method <aclass="el" href="classtf_1_1BasicTaskflow.html#a0126001a2bd8603af4827049578629cb" title="dispatches the present graph to threads and returns immediately ">tf::Taskflow::silent_dispatch</a>. This method does not return anything.</p>
<divclass="fragment"><divclass="line"><aclass="code" href="classtf_1_1BasicTaskflow.html">tf::Taskflow</a> taskflow;</div><divclass="line"></div><divclass="line"><aclass="code" href="classtf_1_1Task.html">tf::Task</a> A = taskflow.<aclass="code" href="classtf_1_1FlowBuilder.html#a4d52a7fe2814b264846a2085e931652c">emplace</a>([] () { <aclass="codeRef" doxygen="/Users/twhuang/PhD/Code/cpp-taskflow/docs/cppreference-doxygen-web.tag.xml:http://en.cppreference.com/w/" href="http://en.cppreference.com/w/cpp/io/basic_ostream.html">std::cout</a> << <spanclass="stringliteral">"TaskA\n"</span>; });</div><divclass="line"><aclass="code" href="classtf_1_1Task.html">tf::Task</a> B = taskflow.<aclass="code" href="classtf_1_1FlowBuilder.html#a4d52a7fe2814b264846a2085e931652c">emplace</a>([] () { <aclass="codeRef" doxygen="/Users/twhuang/PhD/Code/cpp-taskflow/docs/cppreference-doxygen-web.tag.xml:http://en.cppreference.com/w/" href="http://en.cppreference.com/w/cpp/io/basic_ostream.html">std::cout</a> << <spanclass="stringliteral">"TaskB\n"</span>; });</div><divclass="line">A.<aclass="code" href="classtf_1_1Task.html#a8c78c453295a553c1c016e4062da8588">precede</a>(B);</div><divclass="line"></div><divclass="line"><spanclass="keyword">auto</span> F = taskflow.<aclass="code" href="classtf_1_1BasicTaskflow.html#a848e425f67b49a8a7ac21f6b791999c5">dispatch</a>();</div><divclass="line"><spanclass="comment">// do some computation to overlap the execution of tasks A and B</span></div><divclass="line"><spanclass="comment">// ...</span></div></div><!-- fragment --><p>Similarly, the method <code>silent_dispatch</code> has an overload that takes a callable object to execute when the dispatched graph finishes.</p>
<p>Unlike <aclass="el" href="classtf_1_1BasicTaskflow.html#a37ef86998f23ee7315be032c40fe815e" title="dispatches the present graph to threads and wait for all topologies to complete ">tf::Taskflow::wait_for_all</a>, calling <aclass="el" href="classtf_1_1BasicTaskflow.html#a848e425f67b49a8a7ac21f6b791999c5" title="dispatches the present graph to threads and returns immediately ">tf::Taskflow::dispatch</a> or <aclass="el" href="classtf_1_1BasicTaskflow.html#a0126001a2bd8603af4827049578629cb" title="dispatches the present graph to threads and returns immediately ">tf::Taskflow::silent_dispatch</a> will not clean up the topologies upon completion. This allows users to dump the graph structure, in particular, created from dynamic tasking to debug the dependency graph. However, it may be necessary at some points of the program to synchronize with the previously dispatched graphs. Cpp-Taskflow provides a method <aclass="el" href="classtf_1_1BasicTaskflow.html#a8f0ce2026118e97b83cbd727ed0932af" title="blocks until all running topologies complete and then cleans up all associated storages ...">tf::Taskflow::wait_for_topologies</a> for this purpose.</p>
<divclass="fragment"><divclass="line"> 1: <aclass="code" href="classtf_1_1BasicTaskflow.html">tf::Taskflow</a> taskflow(4);</div><divclass="line"> 2: </div><divclass="line"> 3: <aclass="code" href="classtf_1_1Task.html">tf::Task</a> A = taskflow.<aclass="code" href="classtf_1_1FlowBuilder.html#a4d52a7fe2814b264846a2085e931652c">emplace</a>([] () { <aclass="codeRef" doxygen="/Users/twhuang/PhD/Code/cpp-taskflow/docs/cppreference-doxygen-web.tag.xml:http://en.cppreference.com/w/" href="http://en.cppreference.com/w/cpp/io/basic_ostream.html">std::cout</a> << <spanclass="stringliteral">"TaskA\n"</span>; });</div><divclass="line"> 4: <aclass="code" href="classtf_1_1Task.html">tf::Task</a> B = taskflow.<aclass="code" href="classtf_1_1FlowBuilder.html#a4d52a7fe2814b264846a2085e931652c">emplace</a>([] () { <aclass="codeRef" doxygen="/Users/twhuang/PhD/Code/cpp-taskflow/docs/cppreference-doxygen-web.tag.xml:http://en.cppreference.com/w/" href="http://en.cppreference.com/w/cpp/io/basic_ostream.html">std::cout</a> << <spanclass="stringliteral">"TaskB\n"</span>; });</div><divclass="line"> 5: A.<aclass="code" href="classtf_1_1Task.html#a8c78c453295a553c1c016e4062da8588">precede</a>(B);</div><divclass="line"> 6:</div><divclass="line"> 7: <spanclass="keyword">auto</span> F = taskflow.<aclass="code" href="classtf_1_1BasicTaskflow.html#a848e425f67b49a8a7ac21f6b791999c5">dispatch</a>(); <spanclass="comment">// dispatch the present graph</span></div><divclass="line"> 8:</div><divclass="line"> 9: <aclass="code" href="classtf_1_1Task.html">tf::Task</a> C = taskflow.<aclass="code" href="classtf_1_1FlowBuilder.html#a4d52a7fe2814b264846a2085e931652c">emplace</a>([] () { <aclass="codeRef" doxygen="/Users/twhuang/PhD/Code/cpp-taskflow/docs/cppreference-doxygen-web.tag.xml:http://en.cppreference.com/w/" href="http://en.cppreference.com/w/cpp/io/basic_ostream.html">std::cout</a> << <spanclass="stringliteral">"TaskC\n"</span>; });</div><divclass="line">10:</div><divclass="line">11: taskflow.<aclass="code" href="classtf_1_1BasicTaskflow.html#a0126001a2bd8603af4827049578629cb">silent_dispatch</a>(); <spanclass="comment">// dispatch the present graph</span></div><divclass="line">12:</div><divclass="line">13: taskflow.<aclass="code" href="classtf_1_1BasicTaskflow.html#a8f0ce2026118e97b83cbd727ed0932af">wait_for_topologies</a>(); <spanclass="comment">// block until the two graphs finish</span></div><divclass="line">14: </div><divclass="line">15: assert(F.wait_for(<aclass="codeRef" doxygen="/Users/twhuang/PhD/Code/cpp-taskflow/docs/cppreference-doxygen-web.tag.xml:http://en.cppreference.com/w/" href="http://en.cppreference.com/w/cpp/chrono/duration.html">std::chrono::seconds</a>(0)) == std::future_status::ready);</div></div><!-- fragment --><p>Debrief </p><ul>
<li>Line 1 creates a taskflow object with four worker threads </li>
<li>Line 3-5 creates a dependency graph of two tasks and one dependency </li>
<li>Line 7 dispatches this graph to threads and obtains a <aclass="elRef" doxygen="/Users/twhuang/PhD/Code/cpp-taskflow/docs/cppreference-doxygen-web.tag.xml:http://en.cppreference.com/w/" href="http://en.cppreference.com/w/cpp/thread/shared_future.html">std::shared_future</a> object for users to access the execution status </li>
<li>Line 9 starts with a new dependency graph with one task </li>
<li>Line 11 dispatches the graph to threads </li>
<li>Line 13 blocks the program until both graphs finish</li>
</ul>
<p>It is clear now Line 9 overlaps the execution of the first graph. After Line 11, there are two topologies in the taskflow object. Calling the method <aclass="el" href="classtf_1_1BasicTaskflow.html#a8f0ce2026118e97b83cbd727ed0932af" title="blocks until all running topologies complete and then cleans up all associated storages ...">tf::Taskflow::wait_for_topologies</a> blocks the program until both graph complete.</p>
<h1><aclass="anchor" id="LifeTimeOfAGraph"></a>
Lifetime of a Graph</h1>
<p>In Cpp-Taskflow, the lifetime of a task sticks with its parent graph. The lifetime of a task mostly refers to the user-given callable objects, including those captured by a lambda expression. When a graph is destroyed, all of its tasks are destroyed. Consider the following example that uses <aclass="elRef" doxygen="/Users/twhuang/PhD/Code/cpp-taskflow/docs/cppreference-doxygen-web.tag.xml:http://en.cppreference.com/w/" href="http://en.cppreference.com/w/cpp/memory/shared_ptr.html">std::shared_ptr</a> to demonstrate the lifetime of a graph and the impact on its task.</p>
<divclass="fragment"><divclass="line"> 1: <aclass="code" href="classtf_1_1BasicTaskflow.html">tf::Taskflow</a> taskflow;</div><divclass="line"> 2:</div><divclass="line"> 3: <spanclass="keyword">auto</span> ptr = std::make_shared<int>(0);</div><divclass="line"> 4:</div><divclass="line"> 5: <aclass="codeRef" doxygen="/Users/twhuang/PhD/Code/cpp-taskflow/docs/cppreference-doxygen-web.tag.xml:http://en.cppreference.com/w/" href="http://en.cppreference.com/w/cpp/io/basic_ostream.html">std::cout</a> << <spanclass="stringliteral">"reference count before A and B: "</span> << ptr.use_count() << <spanclass="charliteral">'\n'</span>;</div><divclass="line"> 6:</div><divclass="line"> 7: <aclass="code" href="classtf_1_1Task.html">tf::Task</a> A = taskflow.<aclass="code" href="classtf_1_1FlowBuilder.html#a4d52a7fe2814b264846a2085e931652c">emplace</a>([ptr] () {</div><divclass="line"> 8: <aclass="codeRef" doxygen="/Users/twhuang/PhD/Code/cpp-taskflow/docs/cppreference-doxygen-web.tag.xml:http://en.cppreference.com/w/" href="http://en.cppreference.com/w/cpp/io/basic_ostream.html">std::cout</a> << <spanclass="stringliteral">"reference count at A: "</span> << ptr.use_count() << <spanclass="charliteral">'\n'</span>;</div><divclass="line"> 9: });</div><divclass="line">10:</div><divclass="line">11: <aclass="code" href="classtf_1_1Task.html">tf::Task</a> B = taskflow.<aclass="code" href="classtf_1_1FlowBuilder.html#a4d52a7fe2814b264846a2085e931652c">emplace</a>([ptr] () {</div><divclass="line">12: <aclass="codeRef" doxygen="/Users/twhuang/PhD/Code/cpp-taskflow/docs/cppreference-doxygen-web.tag.xml:http://en.cppreference.com/w/" href="http://en.cppreference.com/w/cpp/io/basic_ostream.html">std::cout</a> << <spanclass="stringliteral">"reference count at B: "</span> << ptr.use_count() << <spanclass="charliteral">'\n'</span>;</div><divclass="line">13: });</div><divclass="line">14:</div><divclass="line">15: A.<aclass="code" href="classtf_1_1Task.html#a8c78c453295a553c1c016e4062da8588">precede</a>(B);</div><divclass="line">16:</div><divclass="line">17: <aclass="codeRef" doxygen="/Users/twhuang/PhD/Code/cpp-taskflow/docs/cppreference-doxygen-web.tag.xml:http://en.cppreference.com/w/" href="http://en.cppreference.com/w/cpp/io/basic_ostream.html">std::cout</a> << <spanclass="stringliteral">"reference count after A and B: "</span> << ptr.use_count() << <spanclass="charliteral">'\n'</span>;</div><divclass="line">18:</div><divclass="line">19: taskflow.<aclass="code" href="classtf_1_1BasicTaskflow.html#a37ef86998f23ee7315be032c40fe815e">wait_for_all</a>();</div><divclass="line">20:</div><divclass="line">21: <aclass="codeRef" doxygen="/Users/twhuang/PhD/Code/cpp-taskflow/docs/cppreference-doxygen-web.tag.xml:http://en.cppreference.com/w/" href="http://en.cppreference.com/w/cpp/io/basic_ostream.html">std::cout</a> << <spanclass="stringliteral">"reference count after A and B: "</span> << ptr.use_count() << <spanclass="charliteral">'\n'</span>;</div></div><!-- fragment --><p>The output is as follows:</p>
<divclass="fragment"><divclass="line">reference count before A and B: 1</div><divclass="line">reference count after A and B: 3</div><divclass="line">reference count at A: 3</div><divclass="line">reference count at B: 3</div><divclass="line">reference count after A and B: 1</div></div><!-- fragment --><p>In Line 5, we created a shared pointer object with one reference count on itself. After Line 7-13, the reference count increases by two because task A and task B both capture a copy of the shared pointer. The lifetime of a task has nothing to do with its dependency constraints, as shown in Line 8, Line 12, and Line 17. However, Line 19 dispatches the graph to threads and cleans up its data structure upon finish, including all associated tasks. Therefore, the reference count in Line 21 drops down to one (owner at Line 3).</p>
<p>Now let's use the same example but dispatch the graph asynchronously.</p>
<divclass="fragment"><divclass="line"> 1: <aclass="code" href="classtf_1_1BasicTaskflow.html">tf::Taskflow</a> taskflow;</div><divclass="line"> 2:</div><divclass="line"> 3: <spanclass="keyword">auto</span> ptr = std::make_shared<int>(0);</div><divclass="line"> 4:</div><divclass="line"> 5: <aclass="codeRef" doxygen="/Users/twhuang/PhD/Code/cpp-taskflow/docs/cppreference-doxygen-web.tag.xml:http://en.cppreference.com/w/" href="http://en.cppreference.com/w/cpp/io/basic_ostream.html">std::cout</a> << <spanclass="stringliteral">"reference count before A and B: "</span> << ptr.use_count() << <spanclass="charliteral">'\n'</span>;</div><divclass="line"> 6:</div><divclass="line"> 7: <aclass="code" href="classtf_1_1Task.html">tf::Task</a> A = taskflow.<aclass="code" href="classtf_1_1FlowBuilder.html#a4d52a7fe2814b264846a2085e931652c">emplace</a>([ptr] () {</div><divclass="line"> 8: <aclass="codeRef" doxygen="/Users/twhuang/PhD/Code/cpp-taskflow/docs/cppreference-doxygen-web.tag.xml:http://en.cppreference.com/w/" href="http://en.cppreference.com/w/cpp/io/basic_ostream.html">std::cout</a> << <spanclass="stringliteral">"reference count at A: "</span> << ptr.use_count() << <spanclass="charliteral">'\n'</span>;</div><divclass="line"> 9: });</div><divclass="line">10:</div><divclass="line">11: <aclass="code" href="classtf_1_1Task.html">tf::Task</a> B = taskflow.<aclass="code" href="classtf_1_1FlowBuilder.html#a4d52a7fe2814b264846a2085e931652c">emplace</a>([ptr] () {</div><divclass="line">12: <aclass="codeRef" doxygen="/Users/twhuang/PhD/Code/cpp-taskflow/docs/cppreference-doxygen-web.tag.xml:http://en.cppreference.com/w/" href="http://en.cppreference.com/w/cpp/io/basic_ostream.html">std::cout</a> << <spanclass="stringliteral">"reference count at B: "</span> << ptr.use_count() << <spanclass="charliteral">'\n'</span>;</div><divclass="line">13: });</div><divclass="line">14:</div><divclass="line">15: A.<aclass="code" href="classtf_1_1Task.html#a8c78c453295a553c1c016e4062da8588">precede</a>(B);</div><divclass="line">16:</div><divclass="line">17: <aclass="codeRef" doxygen="/Users/twhuang/PhD/Code/cpp-taskflow/docs/cppreference-doxygen-web.tag.xml:http://en.cppreference.com/w/" href="http://en.cppreference.com/w/cpp/io/basic_ostream.html">std::cout</a> << <spanclass="stringliteral">"reference count after A and B: "</span> << ptr.use_count() << <spanclass="charliteral">'\n'</span>;</div><divclass="line">18:</div><divclass="line">19: taskflow.<aclass="code" href="classtf_1_1BasicTaskflow.html#a848e425f67b49a8a7ac21f6b791999c5">dispatch</a>().get(); <spanclass="comment">// dispatch the graph without destroying it</span></div><divclass="line">20:</div><divclass="line">21: <aclass="codeRef" doxygen="/Users/twhuang/PhD/Code/cpp-taskflow/docs/cppreference-doxygen-web.tag.xml:http://en.cppreference.com/w/" href="http://en.cppreference.com/w/cpp/io/basic_ostream.html">std::cout</a> << <spanclass="stringliteral">"reference count after A and B: "</span> << ptr.use_count() << <spanclass="charliteral">'\n'</span>;</div></div><!-- fragment --><p>In Line 19, we replace <code>wait_for_all</code> with <code>dispatch</code> to dispatch the graph asynchronously without cleaning up its data structures upon completion. In other words, task A and task B remains un-destructed after Line 19, and the reference count at this point remains three.</p>
<divclass="fragment"><divclass="line">reference count before A and B: 1</div><divclass="line">reference count after A and B: 3</div><divclass="line">reference count at A: 3</div><divclass="line">reference count at B: 3</div><divclass="line">reference count after A and B: 3</div></div><!-- fragment --><h1><aclass="anchor" id="Chapter2Example1"></a>
Example 1: Multiple Dispatches</h1>
<p>The example below demonstrates how to create multiple task dependency graphs and dispatch each of them asynchronously.</p>
<li>Line 3 declares a global atomic variable initialized to zero </li>
<li>Line 5-10 defines a function that takes a taskflow object and creates two tasks to increment the counter </li>
<li>Line 12-19 defines a function that iteratively creates a task dependency graph and dispatches it asynchronously </li>
<li>Line 23 starts the procedure of multiple dispatches</li>
</ul>
<p>Notice in Line 24 the counter ends up being 20. By default, destructing a taskflow object will wait on all topologies to finish.</p>
<h1><aclass="anchor" id="Chapter2Example2"></a>
Example 2: Connect Two Dependency Graphs</h1>
<p>The example demonstrates how to use the <aclass="elRef" doxygen="/Users/twhuang/PhD/Code/cpp-taskflow/docs/cppreference-doxygen-web.tag.xml:http://en.cppreference.com/w/" href="http://en.cppreference.com/w/cpp/thread/future.html">std::future</a> to explicitly impose a dependency link on two dispatched graphs.</p>
<divclass="fragment"><divclass="line"> 1: #include <taskflow/taskflow.hpp></div><divclass="line"> 2:</div><divclass="line"> 3: <spanclass="keywordtype">int</span> main() {</div><divclass="line"> 4:</div><divclass="line"> 5: <aclass="code" href="classtf_1_1BasicTaskflow.html">tf::Taskflow</a> taskflow(4);</div><divclass="line"> 6:</div><divclass="line"> 7: <aclass="codeRef" doxygen="/Users/twhuang/PhD/Code/cpp-taskflow/docs/cppreference-doxygen-web.tag.xml:http://en.cppreference.com/w/" href="http://en.cppreference.com/w/cpp/container/vector.html">std::vector<int></a> items; <spanclass="comment">// uninitialized</span></div><divclass="line"> 8: <spanclass="keywordtype">int</span> sum; <spanclass="comment">// uninitialized</span></div><divclass="line"> 9:</div><divclass="line">10: <spanclass="comment">// the first dependency graph</span></div><divclass="line">11: <spanclass="comment">// task C to resize the item vector</span></div><divclass="line">12: <aclass="code" href="classtf_1_1Task.html">tf::Task</a> A = taskflow.<aclass="code" href="classtf_1_1FlowBuilder.html#a4d52a7fe2814b264846a2085e931652c">emplace</a>([&] () { items.resize(1024); });</div><divclass="line">13: </div><divclass="line">14: <spanclass="comment">// task B to initialize the item vector</span></div><divclass="line">15: <aclass="code" href="classtf_1_1Task.html">tf::Task</a> B = taskflow.<aclass="code" href="classtf_1_1FlowBuilder.html#a4d52a7fe2814b264846a2085e931652c">emplace</a>([&] () { <aclass="codeRef" doxygen="/Users/twhuang/PhD/Code/cpp-taskflow/docs/cppreference-doxygen-web.tag.xml:http://en.cppreference.com/w/" href="http://en.cppreference.com/w/cpp/algorithm/iota.html">std::iota</a>(items.begin(), items.end(), 0); });</div><divclass="line">16:</div><divclass="line">17: <spanclass="comment">// A must run before B</span></div><divclass="line">18: A.<aclass="code" href="classtf_1_1Task.html#a8c78c453295a553c1c016e4062da8588">precede</a>(B);</div><divclass="line">19: </div><divclass="line">20: <spanclass="comment">// dispatch the graph asynchronously and obtain the future to access its status</span></div><divclass="line">21: <spanclass="keyword">auto</span> fu1 = taskflow.<aclass="code" href="classtf_1_1BasicTaskflow.html#a848e425f67b49a8a7ac21f6b791999c5">dispatch</a>();</div><divclass="line">22:</div><divclass="line">23: <spanclass="comment">// the second dependency graph</span></div><divclass="line">24: <spanclass="comment">// task C to overlap the exeuction of the first graph</span></div><divclass="line">25: <aclass="code" href="classtf_1_1Task.html">tf::Task</a> C = taskflow.<aclass="code" href="classtf_1_1FlowBuilder.html#a4d52a7fe2814b264846a2085e931652c">emplace</a>([&] () {</div><divclass="line">26: sum = 0; <spanclass="comment">// in practice, this can be some expensive initializations</span></div><divclass="line">27: });</div><divclass="line">28:</div><divclass="line">29: <spanclass="comment">// task D can't start until the first graph completes</span></div><divclass="line">30: <aclass="code" href="classtf_1_1Task.html">tf::Task</a> D = taskflow.<aclass="code" href="classtf_1_1FlowBuilder.html#a4d52a7fe2814b264846a2085e931652c">emplace</a>([&] () {</div><divclass="line">31: fu1.get();</div><divclass="line">32: <spanclass="keywordflow">for</span>(<spanclass="keyword">auto</span> item : items) {</div><divclass="line">33: sum += item;</div><divclass="line">34: }</div><divclass="line">35: });</div><divclass="line">36: </div><divclass="line">37: C.<aclass="code" href="classtf_1_1Task.html#a8c78c453295a553c1c016e4062da8588">precede</a>(D);</div><divclass="line">38: </div><divclass="line">39: <spanclass="keyword">auto</span> fu2 = taskflow.<aclass="code" href="classtf_1_1BasicTaskflow.html#a848e425f67b49a8a7ac21f6b791999c5">dispatch</a>();</div><divclass="line">40: </div><divclass="line">41: <spanclass="comment">// wait on the second dependency graph to finish</span></div><divclass="line">42: fu2.get();</div><divclass="line">43: </div><divclass="line">44: assert(sum == (0 + 1023) * 1024 / 2);</div><divclass="line">45: </div><divclass="line">46: <spanclass="keywordflow">return</span> 0;</div><divclass="line">47: }</div></div><!-- fragment --><p>Debrief: </p><ul>
<li>Line 5 creates a taskflow object with four worker threads </li>
<li>Line 7-8 creates a vector of integer items and an integer variable to store the summation value </li>
<li>Line 10-21 creates a dependency graph that resizes the vector and fills it with sequentially increasing values starting with zero </li>
<li>Line 23-39 creates another dependency graph that sums up the values in the vector </li>
<li>Line 25-27 creates a task that initializes the variable <code>sum</code> to zero, and overlaps its execution with the first dependency graph </li>
<li>Line 30-35 creates a task that blocks until the first dependency graph completes and then sums up all integer values in the properly initialized vector </li>
<li>Line 42 blocks until the second dependency graph finishes </li>
<li>Line 44 puts an assertion guard on the final summation value</li>
</ul>
<p>By the time the second dependency graph finishes, the first dependency graph must have already finished due to Line 31. The result of the variable <code>sum</code> ends up being the summation over the integer sequence [0, 1, 2, ..., 1024). </p>
</div></div><!-- contents -->
</div><!-- doc-content -->
<!-- start footer part -->
<divid="nav-path" class="navpath"><!-- id is needed for treeview function! -->