forked from taskflow/taskflow
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathStaticTasking.html
More file actions
259 lines (255 loc) · 47 KB
/
StaticTasking.html
File metadata and controls
259 lines (255 loc) · 47 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
<!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="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">placeholder</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">"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="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="w"></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="w"></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="w"></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="w"></span>
<span class="mi">9</span><span class="o">:</span><span class="w"> </span><span class="p">);</span><span class="w"></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="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="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="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">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="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="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="w"> </span><span class="mi">8</span><span class="o">:</span><span class="w"></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="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="w"></span>
<span class="p">});</span><span class="w"></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="w"> </span><span class="mi">2</span><span class="o">:</span><span class="w"></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="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="w"> </span><span class="mi">6</span><span class="o">:</span><span class="w"></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="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="w"></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="w"></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="w"></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="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="w"></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="w"></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="w"></span>
<span class="mi">18</span><span class="o">:</span><span class="w"></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="w"></span>
<span class="mi">20</span><span class="o">:</span><span class="w"> </span><span class="p">}</span><span class="w"></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: 15.125rem; height: 6.250rem;" viewBox="0.00 0.00 242.00 99.77">
<g transform="scale(1 1) rotate(0) translate(4 95.7696)">
<title>G</title>
<g class="m-node m-flat">
<title>A</title>
<ellipse cx="27" cy="-45.3848" rx="27" ry="18.2703"/>
<text text-anchor="middle" x="27" y="-41.5848">A</text>
</g>
<g class="m-node m-flat">
<title>B</title>
<ellipse cx="117" cy="-73.3848" rx="27" ry="18.2703"/>
<text text-anchor="middle" x="117" y="-69.5848">B</text>
</g>
<g class="m-edge">
<title>A->B</title>
<path d="M51.5929,-53.0359C61.2164,-56.0299 72.4198,-59.5154 82.8067,-62.7468"/>
<polygon points="81.8485,-66.1142 92.4368,-65.7429 83.928,-59.4302 81.8485,-66.1142"/>
</g>
<g class="m-node m-flat">
<title>C</title>
<ellipse cx="117" cy="-18.3848" rx="27" ry="18.2703"/>
<text text-anchor="middle" x="117" y="-14.5848">C</text>
</g>
<g class="m-edge">
<title>A->C</title>
<path d="M52.07,-37.8638C61.4322,-35.0551 72.2367,-31.8138 82.3123,-28.7911"/>
<polygon points="83.4919,-32.0914 92.0644,-25.8654 81.4804,-25.3866 83.4919,-32.0914"/>
</g>
<g class="m-node m-flat">
<title>D</title>
<ellipse cx="207" cy="-45.3848" rx="27" ry="18.2703"/>
<text text-anchor="middle" x="207" y="-41.5848">D</text>
</g>
<g class="m-edge">
<title>B->D</title>
<path d="M141.5929,-65.7337C151.2164,-62.7397 162.4198,-59.2542 172.8067,-56.0227"/>
<polygon points="173.928,-59.3394 182.4368,-53.0266 171.8485,-52.6554 173.928,-59.3394"/>
</g>
<g class="m-edge">
<title>C->D</title>
<path d="M142.07,-25.9058C151.4322,-28.7144 162.2367,-31.9558 172.3123,-34.9785"/>
<polygon points="171.4804,-38.3829 182.0644,-37.9041 173.4919,-31.6782 171.4804,-38.3829"/>
</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="w"> </span><span class="mi">2</span><span class="o">:</span><span class="w"></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="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="w"> </span><span class="mi">6</span><span class="o">:</span><span class="w"></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="w"></span>
<span class="mi">11</span><span class="o">:</span><span class="w"></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="w"></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="w"></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="w"></span>
<span class="mi">15</span><span class="o">:</span><span class="w"></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="w"></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="w"></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="w"></span>
<span class="mi">20</span><span class="o">:</span><span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="mi">21</span><span class="o">:</span><span class="w"></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="w"></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="w"></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="w"></span>
<span class="mi">26</span><span class="o">:</span><span class="w"></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="w"></span>
<span class="mi">28</span><span class="o">:</span><span class="w"> </span><span class="p">}</span><span class="w"></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="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="w"></span>
<span class="p">});</span><span class="w"></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="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="w"></span>
<span class="p">});</span><span class="w"></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="w"></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="w"></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="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="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="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><span class="w"></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="w"></span>
<span class="n">taskflow1</span><span class="p">.</span><span class="n">emplace</span><span class="p">([](){});</span><span class="w"></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="w"></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="w"></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="w"></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><span class="w"></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–2022.<br />Generated by <a href="https://doxygen.org/">Doxygen</a> 1.8.14 and <a href="https://mcss.mosra.cz/">m.css</a>.</p>
</div>
</div>
</div>
</nav></footer>
</body>
</html>