260 lines
45 KiB
HTML
260 lines
45 KiB
HTML
|
<!DOCTYPE html>
|
||
|
<html lang="en">
|
||
|
<head>
|
||
|
<meta charset="UTF-8" />
|
||
|
<title>Cookbook » Static Tasking | Taskflow QuickStart</title>
|
||
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,400i,600,600i%7CSource+Code+Pro:400,400i,600" />
|
||
|
<link rel="stylesheet" href="m-dark+documentation.compiled.css" />
|
||
|
<link rel="icon" href="favicon.ico" type="image/vnd.microsoft.icon" />
|
||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||
|
<meta name="theme-color" content="#22272e" />
|
||
|
</head>
|
||
|
<body>
|
||
|
<header><nav id="navigation">
|
||
|
<div class="m-container">
|
||
|
<div class="m-row">
|
||
|
<span id="m-navbar-brand" class="m-col-t-8 m-col-m-none m-left-m">
|
||
|
<a href="https://taskflow.github.io"><img src="taskflow_logo.png" alt="" />Taskflow</a> <span class="m-breadcrumb">|</span> <a href="index.html" class="m-thin">QuickStart</a>
|
||
|
</span>
|
||
|
<div class="m-col-t-4 m-hide-m m-text-right m-nopadr">
|
||
|
<a href="#search" class="m-doc-search-icon" title="Search" onclick="return showSearch()"><svg style="height: 0.9rem;" viewBox="0 0 16 16">
|
||
|
<path id="m-doc-search-icon-path" d="m6 0c-3.31 0-6 2.69-6 6 0 3.31 2.69 6 6 6 1.49 0 2.85-0.541 3.89-1.44-0.0164 0.338 0.147 0.759 0.5 1.15l3.22 3.79c0.552 0.614 1.45 0.665 2 0.115 0.55-0.55 0.499-1.45-0.115-2l-3.79-3.22c-0.392-0.353-0.812-0.515-1.15-0.5 0.895-1.05 1.44-2.41 1.44-3.89 0-3.31-2.69-6-6-6zm0 1.56a4.44 4.44 0 0 1 4.44 4.44 4.44 4.44 0 0 1-4.44 4.44 4.44 4.44 0 0 1-4.44-4.44 4.44 4.44 0 0 1 4.44-4.44z"/>
|
||
|
</svg></a>
|
||
|
<a id="m-navbar-show" href="#navigation" title="Show navigation"></a>
|
||
|
<a id="m-navbar-hide" href="#" title="Hide navigation"></a>
|
||
|
</div>
|
||
|
<div id="m-navbar-collapse" class="m-col-t-12 m-show-m m-col-m-none m-right-m">
|
||
|
<div class="m-row">
|
||
|
<ol class="m-col-t-6 m-col-m-none">
|
||
|
<li><a href="pages.html">Handbook</a></li>
|
||
|
<li><a href="namespaces.html">Namespaces</a></li>
|
||
|
</ol>
|
||
|
<ol class="m-col-t-6 m-col-m-none" start="3">
|
||
|
<li><a href="annotated.html">Classes</a></li>
|
||
|
<li><a href="files.html">Files</a></li>
|
||
|
<li class="m-show-m"><a href="#search" class="m-doc-search-icon" title="Search" onclick="return showSearch()"><svg style="height: 0.9rem;" viewBox="0 0 16 16">
|
||
|
<use href="#m-doc-search-icon-path" />
|
||
|
</svg></a></li>
|
||
|
</ol>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
</nav></header>
|
||
|
<main><article>
|
||
|
<div class="m-container m-container-inflatable">
|
||
|
<div class="m-row">
|
||
|
<div class="m-col-l-10 m-push-l-1">
|
||
|
<h1>
|
||
|
<span class="m-breadcrumb"><a href="Cookbook.html">Cookbook</a> »</span>
|
||
|
Static Tasking
|
||
|
</h1>
|
||
|
<nav class="m-block m-default">
|
||
|
<h3>Contents</h3>
|
||
|
<ul>
|
||
|
<li><a href="#CreateATaskDependencyGraph">Create a Task Dependency Graph</a></li>
|
||
|
<li><a href="#VisualizeATaskDependencyGraph">Visualize a Task Dependency Graph</a></li>
|
||
|
<li><a href="#ModifyTaskAttributes">Modify Task Attributes</a></li>
|
||
|
<li><a href="#TraverseAdjacentTasks">Traverse Adjacent Tasks</a></li>
|
||
|
<li><a href="#AttachUserDataToATask">Attach User Data to a Task</a></li>
|
||
|
<li><a href="#UnderstandTheLifetimeOfATask">Understand the Lifetime of a Task</a></li>
|
||
|
<li><a href="#MoveATaskflow">Move a Taskflow</a></li>
|
||
|
</ul>
|
||
|
</nav>
|
||
|
<p>This chapter demonstrates how to create a static task dependency graph. Static tasking captures the static parallel structure of a decomposition and is defined only by the program itself. It has a flat task hierarchy and cannot spawn new tasks from a running dependency graph.</p><section id="CreateATaskDependencyGraph"><h2><a href="#CreateATaskDependencyGraph">Create a Task Dependency Graph</a></h2><p>A task in Taskflow is a <em>callable</em> object for which the operation <a href="https://en.cppreference.com/w/cpp/utility/functional/invoke">std::<wbr />invoke</a> is applicable. It can be either a functor, a lambda expression, a bind expression, or a class objects with <code>operator()</code> overloaded. All tasks are created from <a href="classtf_1_1Taskflow.html" class="m-doc">tf::<wbr />Taskflow</a>, the class that manages a task dependency graph. Taskflow provides two methods, <a href="classtf_1_1FlowBuilder.html#acab0b4ac82260f47fdb36a3244ee3aaf" class="m-doc">tf::<wbr />Taskflow::<wbr />placeholder</a> and <a href="classtf_1_1FlowBuilder.html#a60d7a666cab71ecfa3010b2efb0d6b57" class="m-doc">tf::<wbr />Taskflow::<wbr />emplace</a> to create a task.</p><pre class="m-code"><span class="mi">1</span><span class="o">:</span><span class="w"> </span><span class="n">tf</span><span class="o">::</span><span class="n">Taskflow</span><span class="w"> </span><span class="n">taskflow</span><span class="p">;</span>
|
||
|
<span class="mi">2</span><span class="o">:</span><span class="w"> </span><span class="n">tf</span><span class="o">::</span><span class="n">Task</span><span class="w"> </span><span class="n">A</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">taskflow</span><span class="p">.</span><span class="n">placeholder</span><span class="p">();</span>
|
||
|
<span class="mi">3</span><span class="o">:</span><span class="w"> </span><span class="n">tf</span><span class="o">::</span><span class="n">Task</span><span class="w"> </span><span class="n">B</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">taskflow</span><span class="p">.</span><span class="n">emplace</span><span class="p">([]</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">cout</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="s">"task B</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span><span class="w"> </span><span class="p">});</span>
|
||
|
<span class="mi">4</span><span class="o">:</span>
|
||
|
<span class="mi">5</span><span class="o">:</span><span class="w"> </span><span class="k">auto</span><span class="w"> </span><span class="p">[</span><span class="n">D</span><span class="p">,</span><span class="w"> </span><span class="n">E</span><span class="p">,</span><span class="w"> </span><span class="n">F</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">taskflow</span><span class="p">.</span><span class="n">emplace</span><span class="p">(</span>
|
||
|
<span class="mi">6</span><span class="o">:</span><span class="w"> </span><span class="p">[](){</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">cout</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="s">"Task A</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span><span class="w"> </span><span class="p">},</span>
|
||
|
<span class="mi">7</span><span class="o">:</span><span class="w"> </span><span class="p">[](){</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">cout</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="s">"Task B</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span><span class="w"> </span><span class="p">},</span>
|
||
|
<span class="mi">8</span><span class="o">:</span><span class="w"> </span><span class="p">[](){</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">cout</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="s">"Task C</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span><span class="w"> </span><span class="p">}</span>
|
||
|
<span class="mi">9</span><span class="o">:</span><span class="w"> </span><span class="p">);</span></pre><p>Debrief:</p><ul><li>Line 1 creates a taskflow object, or a <em>graph</em></li><li>Line 2 creates a placeholder task without work (i.e., callable)</li><li>Line 3 creates a task from a given callable object and returns a task handle</li><li>Lines 5-9 create three tasks in one call using C++ structured binding coupled with <a href="http://en.cppreference.com/w/cpp/utility/tuple.html" class="m-doc-external">std::<wbr />tuple</a></li></ul><p>Each time you create a task, the taskflow object creates a node in the task graph and returns a task handle of type <a href="classtf_1_1Task.html" class="m-doc">tf::<wbr />Task</a>. A task handle is a lightweight object that wraps up a particular node in a graph and provides a set of methods for you to assign different attributes to the task such as adding dependencies, naming, and assigning a new work.</p><pre class="m-code"><span class="w"> </span><span class="mi">1</span><span class="o">:</span><span class="w"> </span><span class="n">tf</span><span class="o">::</span><span class="n">Taskflow</span><span class="w"> </span><span class="n">taskflow</span><span class="p">;</span>
|
||
|
<span class="w"> </span><span class="mi">2</span><span class="o">:</span><span class="w"> </span><span class="n">tf</span><span class="o">::</span><span class="n">Task</span><span class="w"> </span><span class="n">A</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">taskflow</span><span class="p">.</span><span class="n">emplace</span><span class="p">([]</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">cout</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="s">"create a task A</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span><span class="w"> </span><span class="p">});</span>
|
||
|
<span class="w"> </span><span class="mi">3</span><span class="o">:</span><span class="w"> </span><span class="n">tf</span><span class="o">::</span><span class="n">Task</span><span class="w"> </span><span class="n">B</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">taskflow</span><span class="p">.</span><span class="n">emplace</span><span class="p">([]</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">cout</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="s">"create a task B</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span><span class="w"> </span><span class="p">});</span>
|
||
|
<span class="w"> </span><span class="mi">4</span><span class="o">:</span>
|
||
|
<span class="w"> </span><span class="mi">5</span><span class="o">:</span><span class="w"> </span><span class="n">A</span><span class="p">.</span><span class="n">name</span><span class="p">(</span><span class="s">"TaskA"</span><span class="p">);</span>
|
||
|
<span class="w"> </span><span class="mi">6</span><span class="o">:</span><span class="w"> </span><span class="n">A</span><span class="p">.</span><span class="n">work</span><span class="p">([]</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">cout</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="s">"reassign A to a new callable</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span><span class="w"> </span><span class="p">});</span>
|
||
|
<span class="w"> </span><span class="mi">7</span><span class="o">:</span><span class="w"> </span><span class="n">A</span><span class="p">.</span><span class="n">precede</span><span class="p">(</span><span class="n">B</span><span class="p">);</span>
|
||
|
<span class="w"> </span><span class="mi">8</span><span class="o">:</span>
|
||
|
<span class="w"> </span><span class="mi">9</span><span class="o">:</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">cout</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="n">A</span><span class="p">.</span><span class="n">name</span><span class="p">()</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span><span class="w"> </span><span class="c1">// TaskA</span>
|
||
|
<span class="mi">10</span><span class="o">:</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">cout</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="n">A</span><span class="p">.</span><span class="n">num_successors</span><span class="p">()</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span><span class="w"> </span><span class="c1">// 1</span>
|
||
|
<span class="mi">11</span><span class="o">:</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">cout</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="n">A</span><span class="p">.</span><span class="n">num_dependents</span><span class="p">()</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span><span class="w"> </span><span class="c1">// 0</span>
|
||
|
<span class="mi">12</span><span class="o">:</span><span class="w"> </span>
|
||
|
<span class="mi">13</span><span class="o">:</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">cout</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="n">B</span><span class="p">.</span><span class="n">num_successors</span><span class="p">()</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span><span class="w"> </span><span class="c1">// 0</span>
|
||
|
<span class="mi">14</span><span class="o">:</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">cout</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="n">B</span><span class="p">.</span><span class="n">num_dependents</span><span class="p">()</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span><span class="w"> </span><span class="c1">// 1</span></pre><p>Debrief:</p><ul><li>Line 1 creates a taskflow object</li><li>Lines 2-3 create two tasks A and B</li><li>Lines 5-6 assign a name and a work to task A, and add a precedence link to task B</li><li>Line 7 adds a dependency link from A to B</li><li>Lines 9-14 dump the task attributes</li></ul><p>Taskflow uses general-purpose polymorphic function wrapper, <a href="http://en.cppreference.com/w/cpp/utility/functional/function.html" class="m-doc-external">std::<wbr />function</a>, to store and invoke a callable in a task. You need to follow its contract to create a task. For example, the callable to construct a task must be copyable, and thus the code below won't compile:</p><pre class="m-code"><span class="n">taskflow</span><span class="p">.</span><span class="n">emplace</span><span class="p">([</span><span class="n">ptr</span><span class="o">=</span><span class="n">std</span><span class="o">::</span><span class="n">make_unique</span><span class="o"><</span><span class="kt">int</span><span class="o">></span><span class="p">(</span><span class="mi">1</span><span class="p">)](){</span>
|
||
|
<span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">cout</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="s">"captured unique pointer is not copyable"</span><span class="p">;</span>
|
||
|
<span class="p">});</span></pre></section><section id="VisualizeATaskDependencyGraph"><h2><a href="#VisualizeATaskDependencyGraph">Visualize a Task Dependency Graph</a></h2><p>You can dump a taskflow to a DOT format and visualize the graph using free online tools such as <a href="https://dreampuf.github.io/GraphvizOnline/">GraphvizOnline</a> and <a href="http://www.webgraphviz.com/">WebGraphviz</a>.</p><pre class="m-code"><span class="w"> </span><span class="mi">1</span><span class="o">:</span><span class="w"> </span><span class="err">#</span><span class="n">include</span><span class="w"> </span><span class="o"><</span><span class="n">taskflow</span><span class="o">/</span><span class="n">taskflow</span><span class="p">.</span><span class="n">hpp</span><span class="o">></span>
|
||
|
<span class="w"> </span><span class="mi">2</span><span class="o">:</span>
|
||
|
<span class="w"> </span><span class="mi">3</span><span class="o">:</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
|
||
|
<span class="w"> </span><span class="mi">4</span><span class="o">:</span><span class="w"> </span>
|
||
|
<span class="w"> </span><span class="mi">5</span><span class="o">:</span><span class="w"> </span><span class="n">tf</span><span class="o">::</span><span class="n">Taskflow</span><span class="w"> </span><span class="n">taskflow</span><span class="p">;</span>
|
||
|
<span class="w"> </span><span class="mi">6</span><span class="o">:</span>
|
||
|
<span class="w"> </span><span class="mi">7</span><span class="o">:</span><span class="w"> </span><span class="c1">// create a task dependency graph</span>
|
||
|
<span class="w"> </span><span class="mi">8</span><span class="o">:</span><span class="w"> </span><span class="n">tf</span><span class="o">::</span><span class="n">Task</span><span class="w"> </span><span class="n">A</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">taskflow</span><span class="p">.</span><span class="n">emplace</span><span class="p">([]</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">cout</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="s">"Task A</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span><span class="w"> </span><span class="p">});</span>
|
||
|
<span class="w"> </span><span class="mi">9</span><span class="o">:</span><span class="w"> </span><span class="n">tf</span><span class="o">::</span><span class="n">Task</span><span class="w"> </span><span class="n">B</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">taskflow</span><span class="p">.</span><span class="n">emplace</span><span class="p">([]</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">cout</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="s">"Task B</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span><span class="w"> </span><span class="p">});</span>
|
||
|
<span class="mi">10</span><span class="o">:</span><span class="w"> </span><span class="n">tf</span><span class="o">::</span><span class="n">Task</span><span class="w"> </span><span class="n">C</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">taskflow</span><span class="p">.</span><span class="n">emplace</span><span class="p">([]</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">cout</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="s">"Task C</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span><span class="w"> </span><span class="p">});</span>
|
||
|
<span class="mi">11</span><span class="o">:</span><span class="w"> </span><span class="n">tf</span><span class="o">::</span><span class="n">Task</span><span class="w"> </span><span class="n">D</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">taskflow</span><span class="p">.</span><span class="n">emplace</span><span class="p">([]</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">cout</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="s">"Task D</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span><span class="w"> </span><span class="p">});</span>
|
||
|
<span class="mi">12</span><span class="o">:</span>
|
||
|
<span class="mi">13</span><span class="o">:</span><span class="w"> </span><span class="c1">// add dependency links</span>
|
||
|
<span class="mi">14</span><span class="o">:</span><span class="w"> </span><span class="n">A</span><span class="p">.</span><span class="n">precede</span><span class="p">(</span><span class="n">B</span><span class="p">);</span><span class="w"> </span>
|
||
|
<span class="mi">15</span><span class="o">:</span><span class="w"> </span><span class="n">A</span><span class="p">.</span><span class="n">precede</span><span class="p">(</span><span class="n">C</span><span class="p">);</span>
|
||
|
<span class="mi">16</span><span class="o">:</span><span class="w"> </span><span class="n">B</span><span class="p">.</span><span class="n">precede</span><span class="p">(</span><span class="n">D</span><span class="p">);</span>
|
||
|
<span class="mi">17</span><span class="o">:</span><span class="w"> </span><span class="n">C</span><span class="p">.</span><span class="n">precede</span><span class="p">(</span><span class="n">D</span><span class="p">);</span>
|
||
|
<span class="mi">18</span><span class="o">:</span>
|
||
|
<span class="mi">19</span><span class="o">:</span><span class="w"> </span><span class="n">taskflow</span><span class="p">.</span><span class="n">dump</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">cout</span><span class="p">);</span>
|
||
|
<span class="mi">20</span><span class="o">:</span><span class="w"> </span><span class="p">}</span></pre><p>Debrief:</p><ul><li>Line 5 creates a taskflow object</li><li>Lines 8-11 create four tasks</li><li>Lines 14-17 add four task dependencies</li><li>Line 19 dumps the taskflow in the DOT format through standard output</li></ul><div class="m-graph"><svg style="width: 24.200rem; height: 9.800rem;" viewBox="0.00 0.00 242.00 98.00">
|
||
|
<g transform="scale(1 1) rotate(0) translate(4 94)">
|
||
|
<title>G</title>
|
||
|
<g class="m-node m-flat">
|
||
|
<title>A</title>
|
||
|
<ellipse cx="27" cy="-45" rx="27" ry="18"/>
|
||
|
<text text-anchor="middle" x="27" y="-42.5" font-family="Helvetica,sans-Serif" font-size="10.00">A</text>
|
||
|
</g>
|
||
|
<g class="m-node m-flat">
|
||
|
<title>B</title>
|
||
|
<ellipse cx="117" cy="-72" rx="27" ry="18"/>
|
||
|
<text text-anchor="middle" x="117" y="-69.5" font-family="Helvetica,sans-Serif" font-size="10.00">B</text>
|
||
|
</g>
|
||
|
<g class="m-edge">
|
||
|
<title>A->B</title>
|
||
|
<path d="M52.05,-52.38C61.44,-55.26 72.36,-58.61 82.5,-61.72"/>
|
||
|
<polygon points="81.7,-65.14 92.29,-64.72 83.75,-58.45 81.7,-65.14"/>
|
||
|
</g>
|
||
|
<g class="m-node m-flat">
|
||
|
<title>C</title>
|
||
|
<ellipse cx="117" cy="-18" rx="27" ry="18"/>
|
||
|
<text text-anchor="middle" x="117" y="-15.5" font-family="Helvetica,sans-Serif" font-size="10.00">C</text>
|
||
|
</g>
|
||
|
<g class="m-edge">
|
||
|
<title>A->C</title>
|
||
|
<path d="M52.05,-37.62C61.44,-34.74 72.36,-31.39 82.5,-28.28"/>
|
||
|
<polygon points="83.75,-31.55 92.29,-25.28 81.7,-24.86 83.75,-31.55"/>
|
||
|
</g>
|
||
|
<g class="m-node m-flat">
|
||
|
<title>D</title>
|
||
|
<ellipse cx="207" cy="-45" rx="27" ry="18"/>
|
||
|
<text text-anchor="middle" x="207" y="-42.5" font-family="Helvetica,sans-Serif" font-size="10.00">D</text>
|
||
|
</g>
|
||
|
<g class="m-edge">
|
||
|
<title>B->D</title>
|
||
|
<path d="M142.05,-64.62C151.44,-61.74 162.36,-58.39 172.5,-55.28"/>
|
||
|
<polygon points="173.75,-58.55 182.29,-52.28 171.7,-51.86 173.75,-58.55"/>
|
||
|
</g>
|
||
|
<g class="m-edge">
|
||
|
<title>C->D</title>
|
||
|
<path d="M142.05,-25.38C151.44,-28.26 162.36,-31.61 172.5,-34.72"/>
|
||
|
<polygon points="171.7,-38.14 182.29,-37.72 173.75,-31.45 171.7,-38.14"/>
|
||
|
</g>
|
||
|
</g>
|
||
|
</svg>
|
||
|
</div></section><section id="ModifyTaskAttributes"><h2><a href="#ModifyTaskAttributes">Modify Task Attributes</a></h2><p>This example demonstrates how to modify a task's attributes using methods defined in the task handler.</p><pre class="m-code"><span class="w"> </span><span class="mi">1</span><span class="o">:</span><span class="w"> </span><span class="err">#</span><span class="n">include</span><span class="w"> </span><span class="o"><</span><span class="n">taskflow</span><span class="o">/</span><span class="n">taskflow</span><span class="p">.</span><span class="n">hpp</span><span class="o">></span>
|
||
|
<span class="w"> </span><span class="mi">2</span><span class="o">:</span>
|
||
|
<span class="w"> </span><span class="mi">3</span><span class="o">:</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
|
||
|
<span class="w"> </span><span class="mi">4</span><span class="o">:</span>
|
||
|
<span class="w"> </span><span class="mi">5</span><span class="o">:</span><span class="w"> </span><span class="n">tf</span><span class="o">::</span><span class="n">Taskflow</span><span class="w"> </span><span class="n">taskflow</span><span class="p">;</span>
|
||
|
<span class="w"> </span><span class="mi">6</span><span class="o">:</span>
|
||
|
<span class="w"> </span><span class="mi">7</span><span class="o">:</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o"><</span><span class="n">tf</span><span class="o">::</span><span class="n">Task</span><span class="o">></span><span class="w"> </span><span class="n">tasks</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="w"> </span>
|
||
|
<span class="w"> </span><span class="mi">8</span><span class="o">:</span><span class="w"> </span><span class="n">taskflow</span><span class="p">.</span><span class="n">placeholder</span><span class="p">(),</span><span class="w"> </span><span class="c1">// create a task with no work</span>
|
||
|
<span class="w"> </span><span class="mi">9</span><span class="o">:</span><span class="w"> </span><span class="n">taskflow</span><span class="p">.</span><span class="n">placeholder</span><span class="p">()</span><span class="w"> </span><span class="c1">// create a task with no work</span>
|
||
|
<span class="mi">10</span><span class="o">:</span><span class="w"> </span><span class="p">};</span>
|
||
|
<span class="mi">11</span><span class="o">:</span>
|
||
|
<span class="mi">12</span><span class="o">:</span><span class="w"> </span><span class="n">tasks</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="n">name</span><span class="p">(</span><span class="s">"This is Task 0"</span><span class="p">);</span>
|
||
|
<span class="mi">13</span><span class="o">:</span><span class="w"> </span><span class="n">tasks</span><span class="p">[</span><span class="mi">1</span><span class="p">].</span><span class="n">name</span><span class="p">(</span><span class="s">"This is Task 1"</span><span class="p">);</span>
|
||
|
<span class="mi">14</span><span class="o">:</span><span class="w"> </span><span class="n">tasks</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="n">precede</span><span class="p">(</span><span class="n">tasks</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span>
|
||
|
<span class="mi">15</span><span class="o">:</span>
|
||
|
<span class="mi">16</span><span class="o">:</span><span class="w"> </span><span class="k">for</span><span class="p">(</span><span class="k">auto</span><span class="w"> </span><span class="n">task</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="n">tasks</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="c1">// print out each task's attributes</span>
|
||
|
<span class="mi">17</span><span class="o">:</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">cout</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="n">task</span><span class="p">.</span><span class="n">name</span><span class="p">()</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="s">": "</span>
|
||
|
<span class="mi">18</span><span class="o">:</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="s">"num_dependents="</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="n">task</span><span class="p">.</span><span class="n">num_dependents</span><span class="p">()</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="s">", "</span>
|
||
|
<span class="mi">19</span><span class="o">:</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="s">"num_successors="</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="n">task</span><span class="p">.</span><span class="n">num_successors</span><span class="p">()</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="sc">'\n'</span><span class="p">;</span>
|
||
|
<span class="mi">20</span><span class="o">:</span><span class="w"> </span><span class="p">}</span>
|
||
|
<span class="mi">21</span><span class="o">:</span>
|
||
|
<span class="mi">22</span><span class="o">:</span><span class="w"> </span><span class="n">taskflow</span><span class="p">.</span><span class="n">dump</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">cout</span><span class="p">);</span><span class="w"> </span><span class="c1">// dump the taskflow graph</span>
|
||
|
<span class="mi">23</span><span class="o">:</span>
|
||
|
<span class="mi">24</span><span class="o">:</span><span class="w"> </span><span class="n">tasks</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="n">work</span><span class="p">([](){</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">cout</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="s">"got a new work!</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span><span class="w"> </span><span class="p">});</span>
|
||
|
<span class="mi">25</span><span class="o">:</span><span class="w"> </span><span class="n">tasks</span><span class="p">[</span><span class="mi">1</span><span class="p">].</span><span class="n">work</span><span class="p">([](){</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">cout</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="s">"got a new work!</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span><span class="w"> </span><span class="p">});</span>
|
||
|
<span class="mi">26</span><span class="o">:</span>
|
||
|
<span class="mi">27</span><span class="o">:</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
|
||
|
<span class="mi">28</span><span class="o">:</span><span class="w"> </span><span class="p">}</span></pre><p>The output of this program looks like the following:</p><pre class="m-code">This is Task <span class="m">0</span>: <span class="nv">num_dependents</span><span class="o">=</span><span class="m">0</span>, <span class="nv">num_successors</span><span class="o">=</span><span class="m">1</span>
|
||
|
This is Task <span class="m">1</span>: <span class="nv">num_dependents</span><span class="o">=</span><span class="m">1</span>, <span class="nv">num_successors</span><span class="o">=</span><span class="m">0</span>
|
||
|
digraph Taskflow <span class="o">{</span>
|
||
|
<span class="s2">"This is Task 1"</span><span class="p">;</span>
|
||
|
<span class="s2">"This is Task 0"</span><span class="p">;</span>
|
||
|
<span class="s2">"This is Task 0"</span> -> <span class="s2">"This is Task 1"</span><span class="p">;</span>
|
||
|
<span class="o">}</span></pre><p>Debrief:</p><ul><li>Line 5 creates a taskflow object</li><li>Lines 7-10 create two placeholder tasks with no works and stores the corresponding task handles in a vector</li><li>Lines 12-13 name the two tasks with human-readable strings</li><li>Line 14 adds a dependency link from the first task to the second task</li><li>Lines 16-20 print out the name of each task, the number of dependents, and the number of successors</li><li>Line 22 dumps the task dependency graph to a <a href="https://dreampuf.github.io/GraphvizOnline/">GraphViz Online</a> format (dot)</li><li>Lines 24-25 assign a new target to each task</li></ul><p>You can change the name and work of a task at anytime before running the graph. The later assignment overwrites the previous values.</p></section><section id="TraverseAdjacentTasks"><h2><a href="#TraverseAdjacentTasks">Traverse Adjacent Tasks</a></h2><p>You can iterate the successor list and the dependent list of a task by using <a href="classtf_1_1Task.html#aff13a503d4a3c994eb08cb6f22e1b427" class="m-doc">tf::<wbr />Task::<wbr />for_each_successor</a> and <a href="classtf_1_1Task.html#a3bf68937662bf291637e4a763476b2e4" class="m-doc">tf::<wbr />Task::<wbr />for_each_dependent</a>, respectively. Each method takes a lambda and applies it to a successor or a dependent being traversed.</p><pre class="m-code"><span class="c1">// traverse all successors of my_task</span>
|
||
|
<span class="n">my_task</span><span class="p">.</span><span class="n">for_each_successor</span><span class="p">([</span><span class="n">s</span><span class="o">=</span><span class="mi">0</span><span class="p">]</span><span class="w"> </span><span class="p">(</span><span class="n">tf</span><span class="o">::</span><span class="n">Task</span><span class="w"> </span><span class="n">successor</span><span class="p">)</span><span class="w"> </span><span class="k">mutable</span><span class="w"> </span><span class="p">{</span>
|
||
|
<span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">cout</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="s">"successor "</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="n">s</span><span class="o">++</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="sc">'\n'</span><span class="p">;</span>
|
||
|
<span class="p">});</span>
|
||
|
|
||
|
<span class="c1">// traverse all dependents of my_task</span>
|
||
|
<span class="n">my_task</span><span class="p">.</span><span class="n">for_each_dependent</span><span class="p">([</span><span class="n">d</span><span class="o">=</span><span class="mi">0</span><span class="p">]</span><span class="w"> </span><span class="p">(</span><span class="n">tf</span><span class="o">::</span><span class="n">Task</span><span class="w"> </span><span class="n">dependent</span><span class="p">)</span><span class="w"> </span><span class="k">mutable</span><span class="w"> </span><span class="p">{</span>
|
||
|
<span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">cout</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="s">"dependent "</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="n">d</span><span class="o">++</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="sc">'\n'</span><span class="p">;</span>
|
||
|
<span class="p">});</span></pre></section><section id="AttachUserDataToATask"><h2><a href="#AttachUserDataToATask">Attach User Data to a Task</a></h2><p>You can attach custom data to a task using <a href="classtf_1_1Task.html#afd82ab6d6518d1142a72c4d2c97ff114" class="m-doc">tf::<wbr />Task::<wbr />data(void*)</a> and access it using <a href="classtf_1_1Task.html#afd82ab6d6518d1142a72c4d2c97ff114" class="m-doc">tf::<wbr />Task::<wbr />data()</a>. Each node in a taskflow is associated with a C-styled data pointer (i.e., <code>void*</code>) you can use to point to user data and access it in the body of a task callable. The following example attaches an integer to a task and accesses that integer through capturing the data in the callable.</p><pre class="m-code"><span class="kt">int</span><span class="w"> </span><span class="n">my_data</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">5</span><span class="p">;</span>
|
||
|
<span class="n">tf</span><span class="o">::</span><span class="n">Task</span><span class="w"> </span><span class="n">task</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">taskflow</span><span class="p">.</span><span class="n">placeholder</span><span class="p">();</span>
|
||
|
<span class="n">task</span><span class="p">.</span><span class="n">data</span><span class="p">(</span><span class="o">&</span><span class="n">my_data</span><span class="p">)</span>
|
||
|
<span class="w"> </span><span class="p">.</span><span class="n">work</span><span class="p">([</span><span class="n">task</span><span class="p">](){</span>
|
||
|
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">my_date</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">*</span><span class="k">static_cast</span><span class="o"><</span><span class="kt">int</span><span class="o">*></span><span class="p">(</span><span class="n">task</span><span class="p">.</span><span class="n">data</span><span class="p">());</span>
|
||
|
<span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">cout</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="s">"my_data: "</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="n">my_data</span><span class="p">;</span><span class="w"> </span>
|
||
|
<span class="w"> </span><span class="p">});</span></pre><p>Notice that you need to create a placeholder task first before assigning it a work callable. Only this way can you capture that task in the lambda and access its attached data in the lambda body.</p><aside class="m-note m-warning"><h4>Attention</h4><p>It is your responsibility to ensure that the attached data stay alive during the execution of its task.</p></aside></section><section id="UnderstandTheLifetimeOfATask"><h2><a href="#UnderstandTheLifetimeOfATask">Understand the Lifetime of a Task</a></h2><p>A task lives with its graph and belongs to only a graph at a time, and is not destroyed until the graph gets cleaned up. The lifetime of a task refers to the user-given callable object, including captured values. As long as the graph is alive, all the associated tasks exist.</p><aside class="m-note m-warning"><h4>Attention</h4><p>It is your responsibility to keep tasks and graph alive during their execution.</p></aside></section><section id="MoveATaskflow"><h2><a href="#MoveATaskflow">Move a Taskflow</a></h2><p>You can construct or assign a taskflow from a <em>moved</em> taskflow. Moving a taskflow to another will result in transferring the underlying graph data structures from one to the other.</p><pre class="m-code"><span class="n">tf</span><span class="o">::</span><span class="n">Taskflow</span><span class="w"> </span><span class="n">taskflow1</span><span class="p">,</span><span class="w"> </span><span class="n">taskflow3</span><span class="p">;</span>
|
||
|
|
||
|
<span class="n">taskflow1</span><span class="p">.</span><span class="n">emplace</span><span class="p">([](){});</span>
|
||
|
|
||
|
<span class="c1">// move-construct taskflow2 from taskflow1</span>
|
||
|
<span class="n">tf</span><span class="o">::</span><span class="n">Taskflow</span><span class="w"> </span><span class="nf">taskflow2</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">move</span><span class="p">(</span><span class="n">taskflow1</span><span class="p">));</span>
|
||
|
<span class="n">assert</span><span class="p">(</span><span class="n">taskflow2</span><span class="p">.</span><span class="n">num_tasks</span><span class="p">()</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="n">taskflow1</span><span class="p">.</span><span class="n">num_tasks</span><span class="p">()</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="p">);</span>
|
||
|
|
||
|
<span class="c1">// move-assign taskflow3 to taskflow2</span>
|
||
|
<span class="n">taskflow3</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">move</span><span class="p">(</span><span class="n">taskflow2</span><span class="p">);</span>
|
||
|
<span class="n">assert</span><span class="p">(</span><span class="n">taskflow3</span><span class="p">.</span><span class="n">num_tasks</span><span class="p">()</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="n">taskflow2</span><span class="p">.</span><span class="n">num_tasks</span><span class="p">()</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="p">);</span></pre><p>You can only move a taskflow to another while that taskflow is not being run by an executor. Moving a running taskflow can result in undefined behavior. Please see <a href="ExecuteTaskflow.html#ExecuteATaskflowWithTransferredOwnership" class="m-doc">Execute a Taskflow with Transferred Ownership</a> for more details.</p></section>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
</article></main>
|
||
|
<div class="m-doc-search" id="search">
|
||
|
<a href="#!" onclick="return hideSearch()"></a>
|
||
|
<div class="m-container">
|
||
|
<div class="m-row">
|
||
|
<div class="m-col-m-8 m-push-m-2">
|
||
|
<div class="m-doc-search-header m-text m-small">
|
||
|
<div><span class="m-label m-default">Tab</span> / <span class="m-label m-default">T</span> to search, <span class="m-label m-default">Esc</span> to close</div>
|
||
|
<div id="search-symbolcount">…</div>
|
||
|
</div>
|
||
|
<div class="m-doc-search-content">
|
||
|
<form>
|
||
|
<input type="search" name="q" id="search-input" placeholder="Loading …" disabled="disabled" autofocus="autofocus" autocomplete="off" spellcheck="false" />
|
||
|
</form>
|
||
|
<noscript class="m-text m-danger m-text-center">Unlike everything else in the docs, the search functionality <em>requires</em> JavaScript.</noscript>
|
||
|
<div id="search-help" class="m-text m-dim m-text-center">
|
||
|
<p class="m-noindent">Search for symbols, directories, files, pages or
|
||
|
modules. You can omit any prefix from the symbol or file path; adding a
|
||
|
<code>:</code> or <code>/</code> suffix lists all members of given symbol or
|
||
|
directory.</p>
|
||
|
<p class="m-noindent">Use <span class="m-label m-dim">↓</span>
|
||
|
/ <span class="m-label m-dim">↑</span> to navigate through the list,
|
||
|
<span class="m-label m-dim">Enter</span> to go.
|
||
|
<span class="m-label m-dim">Tab</span> autocompletes common prefix, you can
|
||
|
copy a link to the result using <span class="m-label m-dim">⌘</span>
|
||
|
<span class="m-label m-dim">L</span> while <span class="m-label m-dim">⌘</span>
|
||
|
<span class="m-label m-dim">M</span> produces a Markdown link.</p>
|
||
|
</div>
|
||
|
<div id="search-notfound" class="m-text m-warning m-text-center">Sorry, nothing was found.</div>
|
||
|
<ul id="search-results"></ul>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
<script src="search-v2.js"></script>
|
||
|
<script src="searchdata-v2.js" async="async"></script>
|
||
|
<footer><nav>
|
||
|
<div class="m-container">
|
||
|
<div class="m-row">
|
||
|
<div class="m-col-l-10 m-push-l-1">
|
||
|
<p>Taskflow handbook is part of the <a href="https://taskflow.github.io">Taskflow project</a>, copyright © <a href="https://tsung-wei-huang.github.io/">Dr. Tsung-Wei Huang</a>, 2018–2024.<br />Generated by <a href="https://doxygen.org/">Doxygen</a> 1.9.1 and <a href="https://mcss.mosra.cz/">m.css</a>.</p>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
</nav></footer>
|
||
|
</body>
|
||
|
</html>
|