开源 企业版 高校版 私有云 模力方舟 AI 队友
代码拉取完成,页面将自动刷新
加入 Gitee
与超过 1400万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
已有帐号? 立即登录
文件
master
分支 (1)
标签 (3)
master
v1.0.2
v1.0.1
v1.0.0
master
分支 (1)
标签 (3)
master
v1.0.2
v1.0.1
v1.0.0
克隆/下载
克隆/下载
提示
下载代码请复制以下命令到终端执行
为确保你提交的代码身份被 Gitee 正确识别,请执行以下命令完成配置
初次使用 SSH 协议进行代码克隆、推送等操作时,需按下述提示完成 SSH 配置
1 生成 RSA 密钥
2 获取 RSA 公钥内容,并配置到 SSH公钥
在 Gitee 上使用 SVN,请访问 使用指南
使用 HTTPS 协议时,命令行会出现如下账号密码验证步骤。基于安全考虑,Gitee 建议 配置并使用私人令牌 替代登录密码进行克隆、推送等操作
Username for 'https://gitee.com': userName
Password for 'https://userName@gitee.com': # 私人令牌
master
分支 (1)
标签 (3)
master
v1.0.2
v1.0.1
v1.0.0
cpp-taskflow
/
docs
/
chapter2.html
cpp-taskflow
/
docs
/
chapter2.html
chapter2.html 21.86 KB
一键复制 编辑 原始数据 按行查看 历史
tsung-wei-huang 提交于 2020年05月12日 06:42 +08:00 . updated docs and README
<!-- HTML header for doxygen 1.8.13-->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.14"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>Cpp-Taskflow</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<link rel="icon" type="image/x-icon" href="favicon.ico" />
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<link href="navtree.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="resize.js"></script>
<script type="text/javascript" src="navtreedata.js"></script>
<script type="text/javascript" src="navtree.js"></script>
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
$(document).ready(initResizable);
/* @license-end */</script>
<link href="search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="search/searchdata.js"></script>
<script type="text/javascript" src="search/search.js"></script>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
<tbody>
<tr style="height: 56px;">
<td id="projectalign" style="padding-left: 0.5em;">
<div id="projectname"><a href="https://github.com/cpp-taskflow/cpp-taskflow">Cpp-Taskflow</a>
&#160;<span id="projectnumber">2.4-master-branch</span>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.14 -->
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
var searchBox = new SearchBox("searchBox", "search",false,'Search');
/* @license-end */
</script>
<script type="text/javascript" src="menudata.js"></script>
<script type="text/javascript" src="menu.js"></script>
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
$(function() {
initMenu('',true,false,'search.php','Search');
$(document).ready(function() { init_search(); });
});
/* @license-end */</script>
<div id="main-nav"></div>
</div><!-- top -->
<div id="side-nav" class="ui-resizable side-nav-resizable">
<div id="nav-tree">
<div id="nav-tree-contents">
<div id="nav-sync" class="sync"></div>
</div>
</div>
<div id="splitbar" style="-moz-user-select:none;"
class="ui-resizable-handle">
</div>
</div>
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
$(document).ready(function(){initNavTree('chapter2.html','');});
/* @license-end */
</script>
<div id="doc-content">
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
onmouseover="return searchBox.OnSearchSelectShow()"
onmouseout="return searchBox.OnSearchSelectHide()"
onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>
<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0"
name="MSearchResults" id="MSearchResults">
</iframe>
</div>
<div class="header">
<div class="headertitle">
<div class="title">C2: Executor </div> </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><p>After you create a task dependency graph, you need to submit it to threads for execution. In this chapter, we will show you how to execute a task dependency graph.</p>
<h1><a class="anchor" id="C2_CreateAnExecutor"></a>
Create an Executor</h1>
<p>To execute a taskflkow, you need to create an <em>executor</em> from <a class="el" href="classtf_1_1Executor.html" title="execution interface for running a taskflow graph ">tf::Executor</a>. An executor is a <em>thread-safe</em> object that manages a set of worker threads and executes tasks through an efficient <em>work-stealing</em> algorithm. Issuing a call to run a taskflow creates a <em>topology</em>, a data structure to keep track of the execution status of a running graph. <a class="el" href="classtf_1_1Executor.html" title="execution interface for running a taskflow graph ">tf::Executor</a> takes an unsigned integer to construct with <code>N</code> worker threads. The default value is <a class="elRef" doxygen="/Users/twhuang/PhD/Code/cpp-taskflow/doxygen/cppreference-doxygen-web.tag.xml:http://en.cppreference.com/w/" href="http://en.cppreference.com/w/cpp/thread/thread/hardware_concurrency.html">std::thread::hardware_concurrency</a>.</p>
<div class="fragment"><div class="line"><a class="code" href="classtf_1_1Executor.html">tf::Executor</a> executor1; <span class="comment">// create an executor of std::thread::hardware_concurrency worker threads</span></div><div class="line"><a class="code" href="classtf_1_1Executor.html">tf::Executor</a> executor2(4); <span class="comment">// create an executor of 4 worker threads</span></div></div><!-- fragment --><p>An executor can be reused to execute multiple taskflows. In most workloads, you may need only one executor to run multiple taskflows where each taskflow represents a part of a parallel decomposition.</p>
<h1><a class="anchor" id="C2_ExecuteATaskflow"></a>
Execute a Taskflow</h1>
<p><a class="el" href="classtf_1_1Executor.html" title="execution interface for running a taskflow graph ">tf::Executor</a> provides a set of <code>run_*</code> methods, <a class="el" href="classtf_1_1Executor.html#a81f35d5b0a20ac0646447eb80d97c0aa" title="runs the taskflow once ">tf::Executor::run</a>, <a class="el" href="classtf_1_1Executor.html#adca6cd0ce1bd7e6fa2ed2a55c9ae15e6" title="runs the taskflow for N times ">tf::Executor::run_n</a>, and <a class="el" href="classtf_1_1Executor.html#a8acf7515e8e8fdda366ace68bcd65aa6" title="runs the taskflow multiple times until the predicate becomes true and then invokes a callback ...">tf::Executor::run_until</a> to run a taskflow for one time, multiple times, or until a given predicate evaluates to true. All methods accept an optional callback to invoke after the execution completes, and return a <a class="elRef" doxygen="/Users/twhuang/PhD/Code/cpp-taskflow/doxygen/cppreference-doxygen-web.tag.xml:http://en.cppreference.com/w/" href="http://en.cppreference.com/w/cpp/thread/future.html">std::future</a> for users to access the execution status. The code below shows several ways to run a taskflow.</p>
<div class="fragment"><div class="line"> 1: <span class="comment">// Declare an executor and a taskflow</span></div><div class="line"> 2: <a class="code" href="classtf_1_1Executor.html">tf::Executor</a> executor;</div><div class="line"> 3: <a class="code" href="classtf_1_1Taskflow.html">tf::Taskflow</a> taskflow;</div><div class="line"> 4:</div><div class="line"> 5: <span class="comment">// Add three tasks into the taskflow</span></div><div class="line"> 6: <a class="code" href="classtf_1_1Task.html">tf::Task</a> A = taskflow.<a class="code" href="classtf_1_1FlowBuilder.html#a796e29175380f70246cf2a5639adc437">emplace</a>([] () { <a class="codeRef" doxygen="/Users/twhuang/PhD/Code/cpp-taskflow/doxygen/cppreference-doxygen-web.tag.xml:http://en.cppreference.com/w/" href="http://en.cppreference.com/w/cpp/io/basic_ostream.html">std::cout</a> &lt;&lt; <span class="stringliteral">&quot;This is TaskA\n&quot;</span>; });</div><div class="line"> 7: <a class="code" href="classtf_1_1Task.html">tf::Task</a> B = taskflow.<a class="code" href="classtf_1_1FlowBuilder.html#a796e29175380f70246cf2a5639adc437">emplace</a>([] () { <a class="codeRef" doxygen="/Users/twhuang/PhD/Code/cpp-taskflow/doxygen/cppreference-doxygen-web.tag.xml:http://en.cppreference.com/w/" href="http://en.cppreference.com/w/cpp/io/basic_ostream.html">std::cout</a> &lt;&lt; <span class="stringliteral">&quot;This is TaskB\n&quot;</span>; });</div><div class="line"> 8: <a class="code" href="classtf_1_1Task.html">tf::Task</a> C = taskflow.<a class="code" href="classtf_1_1FlowBuilder.html#a796e29175380f70246cf2a5639adc437">emplace</a>([] () { <a class="codeRef" doxygen="/Users/twhuang/PhD/Code/cpp-taskflow/doxygen/cppreference-doxygen-web.tag.xml:http://en.cppreference.com/w/" href="http://en.cppreference.com/w/cpp/io/basic_ostream.html">std::cout</a> &lt;&lt; <span class="stringliteral">&quot;This is TaskC\n&quot;</span>; });</div><div class="line"> 9: </div><div class="line">10: <span class="comment">// Build precedence between tasks</span></div><div class="line">11: A.<a class="code" href="classtf_1_1Task.html#a8c78c453295a553c1c016e4062da8588">precede</a>(B, C); </div><div class="line">12: </div><div class="line">13: <a class="codeRef" doxygen="/Users/twhuang/PhD/Code/cpp-taskflow/doxygen/cppreference-doxygen-web.tag.xml:http://en.cppreference.com/w/" href="http://en.cppreference.com/w/cpp/thread/future.html">std::future&lt;void&gt;</a> fu = executor.<a class="code" href="classtf_1_1Executor.html#a81f35d5b0a20ac0646447eb80d97c0aa">run</a>(taskflow);</div><div class="line">14: fu.wait(); <span class="comment">// block until the execution completes</span></div><div class="line">15:</div><div class="line">16: executor.<a class="code" href="classtf_1_1Executor.html#a81f35d5b0a20ac0646447eb80d97c0aa">run</a>(taskflow, [](){ <a class="codeRef" doxygen="/Users/twhuang/PhD/Code/cpp-taskflow/doxygen/cppreference-doxygen-web.tag.xml:http://en.cppreference.com/w/" href="http://en.cppreference.com/w/cpp/io/basic_ostream.html">std::cout</a> &lt;&lt; <span class="stringliteral">&quot;end of one execution\n&quot;</span>; }).wait();</div><div class="line">17: executor.<a class="code" href="classtf_1_1Executor.html#adca6cd0ce1bd7e6fa2ed2a55c9ae15e6">run_n</a>(taskflow, 4);</div><div class="line">18: executor.<a class="code" href="classtf_1_1Executor.html#ab9aa252f70e9a40020a1e5a89d485b85">wait_for_all</a>(); <span class="comment">// block until all associated executions finish</span></div><div class="line">19: executor.<a class="code" href="classtf_1_1Executor.html#adca6cd0ce1bd7e6fa2ed2a55c9ae15e6">run_n</a>(taskflow, 4, [](){ <a class="codeRef" doxygen="/Users/twhuang/PhD/Code/cpp-taskflow/doxygen/cppreference-doxygen-web.tag.xml:http://en.cppreference.com/w/" href="http://en.cppreference.com/w/cpp/io/basic_ostream.html">std::cout</a> &lt;&lt; <span class="stringliteral">&quot;end of four executions\n&quot;</span>; }).wait();</div><div class="line">20: executor.<a class="code" href="classtf_1_1Executor.html#a8acf7515e8e8fdda366ace68bcd65aa6">run_until</a>(taskflow, [<span class="keywordtype">int</span> cnt=0] () <span class="keyword">mutable</span> { <span class="keywordflow">return</span> (++cnt == 10); });</div></div><!-- fragment --><p>Debrief:</p>
<ul>
<li>Line 6-8 creates a taskflow of three tasks A, B, and C </li>
<li>Line 13-14 runs the taskflow once and use <a class="elRef" doxygen="/Users/twhuang/PhD/Code/cpp-taskflow/doxygen/cppreference-doxygen-web.tag.xml:http://en.cppreference.com/w/" href="http://en.cppreference.com/w/cpp/thread/future/wait.html">std::future::wait</a> to wait for completion </li>
<li>Line 16 runs the taskflow once with a callback to invoke when the execution finishes </li>
<li>Line 17-18 runs the taskflow four times and use <a class="el" href="classtf_1_1Executor.html#ab9aa252f70e9a40020a1e5a89d485b85" title="wait for all pending graphs to complete ">tf::Executor::wait_for_all</a> to wait for completion </li>
<li>Line 19 runs the taskflow four times and invokes a callback at the end of the forth execution </li>
<li>Line 20 keeps running the taskflow until the predicate returns true</li>
</ul>
<p>Issuing multiple runs on the same taskflow will automatically <em>synchronize</em> to a sequential chain of executions in the order of run calls.</p>
<div class="fragment"><div class="line">executor.<a class="code" href="classtf_1_1Executor.html#a81f35d5b0a20ac0646447eb80d97c0aa">run</a>(taskflow); <span class="comment">// execution 1</span></div><div class="line">executor.<a class="code" href="classtf_1_1Executor.html#adca6cd0ce1bd7e6fa2ed2a55c9ae15e6">run_n</a>(taskflow, 10); <span class="comment">// execution 2</span></div><div class="line">executor.<a class="code" href="classtf_1_1Executor.html#a81f35d5b0a20ac0646447eb80d97c0aa">run</a>(taskflow); <span class="comment">// execution 3</span></div><div class="line">executor.<a class="code" href="classtf_1_1Executor.html#ab9aa252f70e9a40020a1e5a89d485b85">wait_for_all</a>(); <span class="comment">// execution 1 -&gt; execution 2 -&gt; execution 3</span></div></div><!-- fragment --><p>A key point to notice is a running taskflow must remain alive during its execution. It is your responsibility to ensure a taskflow not being destructed when it is running. For example, the code below can result undefined behavior.</p>
<div class="fragment"><div class="line"><a class="code" href="classtf_1_1Executor.html">tf::Executor</a> executor; <span class="comment">// create an executor</span></div><div class="line"></div><div class="line"><span class="comment">// create a taskflow whose lifetime is restricted by the scope</span></div><div class="line">{</div><div class="line"> <a class="code" href="classtf_1_1Taskflow.html">tf::Taskflow</a> taskflow;</div><div class="line"> </div><div class="line"> <span class="comment">// add tasks to the taskflow</span></div><div class="line"> <span class="comment">// ... </span></div><div class="line"></div><div class="line"> <span class="comment">// run the taskflow</span></div><div class="line"> executor.<a class="code" href="classtf_1_1Executor.html#a81f35d5b0a20ac0646447eb80d97c0aa">run</a>(f);</div><div class="line"></div><div class="line">} <span class="comment">// at this point, taskflow might get destructed while it is running, resulting in defined behavior</span></div></div><!-- fragment --><p>Similarly, you should avoid touching a taskflow while it is running.</p>
<div class="fragment"><div class="line"><a class="code" href="classtf_1_1Taskflow.html">tf::Taskflow</a> taskflow;</div><div class="line"></div><div class="line"><span class="comment">// Add tasks into the taskflow</span></div><div class="line"><span class="comment">// ...</span></div><div class="line"></div><div class="line"><span class="comment">// Declare an executor</span></div><div class="line"><a class="code" href="classtf_1_1Executor.html">tf::Executor</a> executor;</div><div class="line"></div><div class="line"><a class="codeRef" doxygen="/Users/twhuang/PhD/Code/cpp-taskflow/doxygen/cppreference-doxygen-web.tag.xml:http://en.cppreference.com/w/" href="http://en.cppreference.com/w/cpp/thread/future.html">std::future&lt;void&gt;</a> future = taskflow.run(f); <span class="comment">// non-blocking return</span></div><div class="line"></div><div class="line"><span class="comment">// alter the taskflow while running leads to undefined behavior </span></div><div class="line">f.<a class="code" href="classtf_1_1FlowBuilder.html#a796e29175380f70246cf2a5639adc437">emplace</a>([](){ <a class="codeRef" doxygen="/Users/twhuang/PhD/Code/cpp-taskflow/doxygen/cppreference-doxygen-web.tag.xml:http://en.cppreference.com/w/" href="http://en.cppreference.com/w/cpp/io/basic_ostream.html">std::cout</a> &lt;&lt; <span class="stringliteral">&quot;Add a new task\n&quot;</span>; });</div></div><!-- fragment --><p>A rule of thumb is to always keep a taskflow alive in your function scope while it is participating in an execution.</p>
<h1><a class="anchor" id="C2_ThreadSafety"></a>
Thread Safety</h1>
<p><a class="el" href="classtf_1_1Executor.html" title="execution interface for running a taskflow graph ">tf::Executor</a> is <em>thread-safe</em>. Touching an executor from multiple threads is acceptable. You can have multiple threads call the same executor to run different taskflows.</p>
<div class="fragment"><div class="line">1: <a class="code" href="classtf_1_1Executor.html">tf::Executor</a> executor;</div><div class="line">2:</div><div class="line">3: <span class="keywordflow">for</span>(<span class="keywordtype">int</span> i=0; i&lt;10; ++i) {</div><div class="line">4: <a class="codeRef" doxygen="/Users/twhuang/PhD/Code/cpp-taskflow/doxygen/cppreference-doxygen-web.tag.xml:http://en.cppreference.com/w/" href="http://en.cppreference.com/w/cpp/thread/thread.html">std::thread</a>([i, &amp;](){</div><div class="line">5: <span class="comment">// ... modify my taskflow</span></div><div class="line">6: executor.<a class="code" href="classtf_1_1Executor.html#a81f35d5b0a20ac0646447eb80d97c0aa">run</a>(taskflows[i]); <span class="comment">// run my taskflow</span></div><div class="line">7: }).detach();</div><div class="line">8: }</div></div><!-- fragment --><h1><a class="anchor" id="C2_MonitorThreadActivities"></a>
Monitor Thread Activities</h1>
<p>Inspecting the thread activities is very important for performance analysis. It allows you to know when each task starts and ends participating in the task scheduling. Cpp-Taskflow provides a default observer class tf::ExecutorObserver for this purpose. The following example shows how to create an observer from an executor.</p>
<div class="fragment"><div class="line"><a class="code" href="classtf_1_1Executor.html">tf::Executor</a> executor;</div><div class="line"><a class="code" href="classtf_1_1ChromeTracingObserver.html">tf::ExecutorObserver</a>* observer = executor.<a class="code" href="classtf_1_1Executor.html#a3e68a0d779cfee1554c88c2596ae9000">make_observer</a>&lt;<a class="code" href="classtf_1_1ChromeTracingObserver.html">tf::ExecutorObserver</a>&gt;();</div></div><!-- fragment --><p>Note that each executor can only have an observer at a time. An observer will automatically record the start and end timestamps of each executed task. Users can query, dump or remove the timestamps through the <a class="el" href="classtf_1_1ChromeTracingObserver.html#a996fcaf138dd62ea9edbb3e013e921a9" title="get the number of total tasks in the observer ">tf::ExecutorObserver::num_tasks</a>, <a class="el" href="classtf_1_1ChromeTracingObserver.html#af443dbf15bfba3f35686b7cdfc1aee38" title="dump the timelines in JSON format to an ostream ">tf::ExecutorObserver::dump</a> and <a class="el" href="classtf_1_1ChromeTracingObserver.html#a80b781d1df8f31c2b73df55b36d2e104" title="clear the timeline data ">tf::ExecutorObserver::clear</a> methods.</p>
<div class="fragment"><div class="line"> 1: <a class="code" href="classtf_1_1Executor.html">tf::Executor</a> executor;</div><div class="line"> 2: <a class="code" href="classtf_1_1ChromeTracingObserver.html">tf::ExecutorObserver</a>* observer = executor.<a class="code" href="classtf_1_1Executor.html#a3e68a0d779cfee1554c88c2596ae9000">make_observer</a>&lt;<a class="code" href="classtf_1_1ChromeTracingObserver.html">tf::ExecutorObserver</a>&gt;();</div><div class="line"> 3:</div><div class="line"> 4: executor.<a class="code" href="classtf_1_1Executor.html#a81f35d5b0a20ac0646447eb80d97c0aa">run</a>(taskflow).get(); <span class="comment">// do something</span></div><div class="line"> 5:</div><div class="line"> 6: <span class="comment">// Query the total number of tasks (number of timestamp pairs)</span></div><div class="line"> 7: <span class="keyword">auto</span> num_tasks = observer-&gt;<a class="code" href="classtf_1_1ChromeTracingObserver.html#a996fcaf138dd62ea9edbb3e013e921a9">num_tasks</a>();</div><div class="line"> 8:</div><div class="line"> 9: <span class="comment">// Dump the timeline data in JSON format </span></div><div class="line">10: <a class="codeRef" doxygen="/Users/twhuang/PhD/Code/cpp-taskflow/doxygen/cppreference-doxygen-web.tag.xml:http://en.cppreference.com/w/" href="http://en.cppreference.com/w/cpp/string/basic_string.html">std::string</a> timelines_in_json = observer-&gt;<a class="code" href="classtf_1_1ChromeTracingObserver.html#af443dbf15bfba3f35686b7cdfc1aee38">dump</a>();</div><div class="line">11: </div><div class="line">12: <span class="comment">// Clear the timeline data</span></div><div class="line">13: observer-&gt;<a class="code" href="classtf_1_1ChromeTracingObserver.html#a80b781d1df8f31c2b73df55b36d2e104">clear</a>();</div></div><!-- fragment --><p>Debrief:</p>
<ul>
<li>Line 2-4 creates an observer and a task dependency graph with four tasks and submits the tasks to execution. </li>
<li>Line 7 query the total number of tasks (number of timestamp pair) through observer </li>
<li>Line 10 dump the timestamps to a <a class="elRef" doxygen="/Users/twhuang/PhD/Code/cpp-taskflow/doxygen/cppreference-doxygen-web.tag.xml:http://en.cppreference.com/w/" href="http://en.cppreference.com/w/cpp/string/basic_string.html">std::string</a> in JSON format </li>
<li>Line 13 remove all timestamps in the observer</li>
</ul>
<p>You can visualize the timeline data in a Chrome browser:</p>
<ul>
<li>Step 1: save the JSON timeline data to a file </li>
<li>Step 2: launch the Chrome browser and open a tab with the url: chrome://tracing </li>
<li>Step 3: load the JSON file</li>
</ul>
<div class="image">
<img src="timeline.png" alt="timeline.png" width="80%"/>
</div>
<p>Tasks will be categorized by the executing thread and each task is named with <em>i_j</em> where <em>i</em> is the thread id and <em>j</em> is the task number. You can pan or zoom in/out the timeline to get a detailed view.</p>
<h1><a class="anchor" id="C2_CustomizeYourOwnObserver"></a>
Customize Your Own Observer</h1>
<p>You can derive your own observer from the base interface class tf::ExecutorObserverInterface to customize the observing methods. </p>
</div></div><!-- contents -->
</div><!-- doc-content -->
<!-- start footer part -->
<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
<ul>
<li class="navelem"><a class="el" href="Cookbook.html">Cookbook</a></li>
<li class="footer">Generated by
<a href="http://www.doxygen.org/index.html">
<img class="footer" src="doxygen.png" alt="doxygen"/></a> 1.8.14 </li>
</ul>
</div>
</body>
</html>
Loading...
举报
举报成功
我们将于2个工作日内通过站内信反馈结果给你!
请认真填写举报原因,尽可能描述详细。
请选择举报类型
取消
发送
误判申诉

此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。

如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。

取消
提交

简介

Fast C++ Parallel Programming with Task Dependencies
取消

发行版

暂无发行版

贡献者

全部

近期动态

不能加载更多了
编辑仓库简介
简介内容
主页
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
C++
1
https://gitee.com/tomgee/cpp-taskflow.git
git@gitee.com:tomgee/cpp-taskflow.git
tomgee
cpp-taskflow
cpp-taskflow
master
点此查找更多帮助

搜索帮助

评论
仓库举报
回到顶部
登录提示
该操作需登录 Gitee 帐号,请先登录后再操作。
立即登录
没有帐号,去注册

AltStyle によって変換されたページ (->オリジナル) /