同步操作将从 Gitee 极速下载/cpp-taskflow 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
<?xml version='1.0' encoding='UTF-8' standalone='no'?><doxygen xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="compound.xsd" version="1.8.14"><compounddef id="AsyncTasking" kind="page"><compoundname>AsyncTasking</compoundname><title>Asynchronous Tasking</title><tableofcontents/><briefdescription></briefdescription><detaileddescription><para>This chapters discusses how to launch tasks asynchronously so that you can incorporate independent, dynamic parallelism in your taskflows.</para><sect1 id="AsyncTasking_1LaunchAsynchronousTasksFromAnExecutor"><title>Launch Asynchronous Tasks from an Executor</title><para>Taskflow executor provides a STL-styled method, <ref refid="classtf_1_1Executor_1a1e6866c8f1b6a2e932f06d0b4eb032c0" kindref="member">tf::Executor::async</ref>, for you to run a callable object asynchronously. The method returns a <ref refid="classtf_1_1Future" kindref="compound">tf::Future</ref> object derived from <ulink url="https://en.cppreference.com/w/cpp/thread/future">std::future</ulink> that will eventually hold the result of that function call. The result may be optional due to <ref refid="classtf_1_1Future_1a3bf5f104864ab2590b6409712d3a469b" kindref="member">tf::Future::cancel</ref> (see <ref refid="RequestCancellation" kindref="compound">Request Cancellation</ref> for details).</para><para><programlisting filename=".cpp"><codeline><highlight class="normal"><ref refid="classtf_1_1Future" kindref="compound">tf::Future<std::optional<int></ref>><sp/>future<sp/>=<sp/>executor.<ref refid="classtf_1_1Executor_1a1e6866c8f1b6a2e932f06d0b4eb032c0" kindref="member">async</ref>([](){<sp/></highlight><highlight class="keywordflow">return</highlight><highlight class="normal"><sp/>1;<sp/>});</highlight></codeline><codeline><highlight class="normal">executor.<ref refid="classtf_1_1Executor_1ab9aa252f70e9a40020a1e5a89d485b85" kindref="member">wait_for_all</ref>();</highlight></codeline><codeline><highlight class="normal">assert(future.get()<sp/>==<sp/>1);</highlight></codeline><codeline><highlight class="normal"></highlight></codeline><codeline><highlight class="normal"><ref refid="classtf_1_1Future" kindref="compound">tf::Future<void></ref><sp/>future_of_void_return<sp/>=<sp/>executor.<ref refid="classtf_1_1Executor_1a1e6866c8f1b6a2e932f06d0b4eb032c0" kindref="member">async</ref>([](){});</highlight></codeline><codeline><highlight class="normal">future_of_void_return.get();</highlight></codeline></programlisting></para><para><simplesect kind="note"><para>The future object returned from <ref refid="classtf_1_1Executor_1a1e6866c8f1b6a2e932f06d0b4eb032c0" kindref="member">tf::Executor::async</ref> does not block on destruction.</para></simplesect>If you do not need the return value or the future, you can use <ref refid="classtf_1_1Executor_1abf71e7ec0026ddfce79c912264369bc9" kindref="member">tf::Executor::silent_async</ref> which has less overhead of creating an asynchronous task compared to <ref refid="classtf_1_1Executor_1a1e6866c8f1b6a2e932f06d0b4eb032c0" kindref="member">tf::Executor::async</ref>.</para><para><programlisting filename=".cpp"><codeline><highlight class="normal">executor.<ref refid="classtf_1_1Executor_1abf71e7ec0026ddfce79c912264369bc9" kindref="member">silent_async</ref>([](){</highlight></codeline><codeline><highlight class="normal"><sp/><sp/></highlight><highlight class="comment">//<sp/>just<sp/>do<sp/>some<sp/>stuff<sp/>in<sp/>the<sp/>background<sp/>...</highlight><highlight class="normal"></highlight></codeline><codeline><highlight class="normal">});</highlight></codeline></programlisting></para><para>Launching asynchronous tasks from an executor is <emphasis>thread-safe</emphasis> and can be called from multiple threads or from the execution of a task. Our scheduler autonomously detects whether an asynchronous task is submitted from an external thread or a worker thread and schedules its execution in an efficient work-stealing loop.</para><para><programlisting filename=".cpp"><codeline><highlight class="normal"><ref refid="classtf_1_1Task" kindref="compound">tf::Task</ref><sp/>my_task<sp/>=<sp/>taskflow.<ref refid="classtf_1_1FlowBuilder_1a60d7a666cab71ecfa3010b2efb0d6b57" kindref="member">emplace</ref>([&](){</highlight></codeline><codeline><highlight class="normal"><sp/><sp/></highlight><highlight class="comment">//<sp/>do<sp/>some<sp/>stuff</highlight><highlight class="normal"></highlight></codeline><codeline><highlight class="normal"><sp/><sp/></highlight><highlight class="comment">//<sp/>...</highlight><highlight class="normal"></highlight></codeline><codeline><highlight class="normal"><sp/><sp/></highlight><highlight class="comment">//<sp/>launch<sp/>an<sp/>asynchronous<sp/>task<sp/>from<sp/>my_task</highlight><highlight class="normal"></highlight></codeline><codeline><highlight class="normal"><sp/><sp/>executor.<ref refid="classtf_1_1Executor_1a1e6866c8f1b6a2e932f06d0b4eb032c0" kindref="member">async</ref>([&](){</highlight></codeline><codeline><highlight class="normal"><sp/><sp/><sp/><sp/></highlight><highlight class="comment">//<sp/>do<sp/>another<sp/>asynchronous<sp/>work</highlight><highlight class="normal"></highlight></codeline><codeline><highlight class="normal"><sp/><sp/><sp/><sp/></highlight><highlight class="comment">//<sp/>...</highlight><highlight class="normal"></highlight></codeline><codeline><highlight class="normal"><sp/><sp/><sp/><sp/></highlight><highlight class="comment">//<sp/>launch<sp/>another<sp/>asynchronous<sp/>task</highlight><highlight class="normal"></highlight></codeline><codeline><highlight class="normal"><sp/><sp/><sp/><sp/>executor.<ref refid="classtf_1_1Executor_1a1e6866c8f1b6a2e932f06d0b4eb032c0" kindref="member">async</ref>([&](){});</highlight></codeline><codeline><highlight class="normal"><sp/><sp/>})</highlight></codeline><codeline><highlight class="normal">});</highlight></codeline><codeline><highlight class="normal">executor.<ref refid="classtf_1_1Executor_1a519777f5783981d534e9e53b99712069" kindref="member">run</ref>(taskflow);</highlight></codeline><codeline><highlight class="normal">executor.<ref refid="classtf_1_1Executor_1ab9aa252f70e9a40020a1e5a89d485b85" kindref="member">wait_for_all</ref>();<sp/><sp/><sp/></highlight><highlight class="comment">//<sp/>wait<sp/>for<sp/>all<sp/>tasks<sp/>to<sp/>finish</highlight></codeline></programlisting></para><para><simplesect kind="note"><para>Asynchronous tasks created from an executor does not belong to any taskflows.</para></simplesect>You can name an asynchronous task to facilitate profiling by using the methods <ref refid="classtf_1_1Executor_1a51acee1670e9f246c7ccd7f6a63f1524" kindref="member">tf::Executor::named_async</ref> and <ref refid="classtf_1_1Executor_1a1febfaa7a99cac8466263c58fd2a7c06" kindref="member">tf::Executor::named_silent_async</ref>.</para><para><programlisting filename=".cpp"><codeline><highlight class="normal"><ref refid="classtf_1_1Future" kindref="compound">tf::Future<void></ref><sp/>future<sp/>=<sp/>executor.<ref refid="classtf_1_1Executor_1a51acee1670e9f246c7ccd7f6a63f1524" kindref="member">named_async</ref>(</highlight><highlight class="stringliteral">"name<sp/>of<sp/>the<sp/>task"</highlight><highlight class="normal">,<sp/>[](){});</highlight></codeline><codeline><highlight class="normal">executor.silent_named_async(</highlight><highlight class="stringliteral">"another<sp/>name<sp/>of<sp/>the<sp/>task"</highlight><highlight class="normal">,<sp/>[](){});</highlight></codeline></programlisting></para></sect1><sect1 id="AsyncTasking_1LaunchAsynchronousTasksFromAnSubflow"><title>Launch Asynchronous Tasks from a Subflow</title><para>You can launch asynchronous tasks from a subflow (<ref refid="classtf_1_1Subflow" kindref="compound">tf::Subflow</ref>) using <ref refid="classtf_1_1Subflow_1a70681068507b224a96df69cc1f3168f1" kindref="member">tf::Subflow::async</ref>. Asynchronous tasks created from a subflow are, and <emphasis>only</emphasis>, used with <emphasis>join</emphasis> (<ref refid="classtf_1_1Subflow_1a59fcac1323e70d920088dd37bd0be245" kindref="member">tf::Subflow::join</ref>) to describe independent tasks that are dynamically spawned during the execution of that subflow. When the subflow joins, all asynchronous tasks are guaranteed to finish. The following code creates 100 asynchronous tasks from a subflow, and these asynchronous tasks will complete by the time the subflow joins.</para><para><programlisting filename=".cpp"><codeline><highlight class="normal"><ref refid="classtf_1_1Taskflow" kindref="compound">tf::Taskflow</ref><sp/>taskflow;</highlight></codeline><codeline><highlight class="normal"><ref refid="classtf_1_1Executor" kindref="compound">tf::Executor</ref><sp/>executor;</highlight></codeline><codeline><highlight class="normal"></highlight></codeline><codeline><highlight class="normal"><ref refid="cpp/atomic/atomic" kindref="compound" external="/home/twhuang/Code/taskflow/doxygen/cppreference-doxygen-web.tag.xml">std::atomic<int></ref><sp/>counter{0};</highlight></codeline><codeline><highlight class="normal"></highlight></codeline><codeline><highlight class="normal">taskflow.<ref refid="classtf_1_1FlowBuilder_1a60d7a666cab71ecfa3010b2efb0d6b57" kindref="member">emplace</ref>([&]<sp/>(<ref refid="classtf_1_1Subflow" kindref="compound">tf::Subflow</ref>&<sp/>sf){</highlight></codeline><codeline><highlight class="normal"><sp/><sp/><ref refid="cpp/container/vector" kindref="compound" external="/home/twhuang/Code/taskflow/doxygen/cppreference-doxygen-web.tag.xml">std::vector<tf::Future<void></ref>><sp/>futures;</highlight></codeline><codeline><highlight class="normal"><sp/><sp/></highlight><highlight class="keywordflow">for</highlight><highlight class="normal">(</highlight><highlight class="keywordtype">int</highlight><highlight class="normal"><sp/>i=0;<sp/>i<100;<sp/>i++)<sp/>{</highlight></codeline><codeline><highlight class="normal"><sp/><sp/><sp/><sp/>futures.emplace_back(sf.<ref refid="classtf_1_1Subflow_1a70681068507b224a96df69cc1f3168f1" kindref="member">async</ref>([&](){<sp/>++counter;<sp/>}));</highlight></codeline><codeline><highlight class="normal"><sp/><sp/>}</highlight></codeline><codeline><highlight class="normal"><sp/><sp/>sf.<ref refid="classtf_1_1Subflow_1a59fcac1323e70d920088dd37bd0be245" kindref="member">join</ref>();<sp/><sp/></highlight><highlight class="comment">//<sp/>all<sp/>of<sp/>the<sp/>100<sp/>asynchronous<sp/>tasks<sp/>will<sp/>finish<sp/>by<sp/>this<sp/>join</highlight><highlight class="normal"></highlight></codeline><codeline><highlight class="normal"><sp/><sp/>assert(counter<sp/>==<sp/>100);</highlight></codeline><codeline><highlight class="normal">});</highlight></codeline><codeline><highlight class="normal"></highlight></codeline><codeline><highlight class="normal">executor.<ref refid="classtf_1_1Executor_1a519777f5783981d534e9e53b99712069" kindref="member">run</ref>(taskflow).wait();</highlight></codeline></programlisting></para><para>If you do not need the return value or the future, you can use <ref refid="classtf_1_1Subflow_1af9671aa8548882b3425e5a1f10f7a868" kindref="member">tf::Subflow::silent_async</ref> which has less overhead of creating an asynchronous task compared to <ref refid="classtf_1_1Subflow_1a70681068507b224a96df69cc1f3168f1" kindref="member">tf::Subflow::async</ref>.</para><para><programlisting filename=".cpp"><codeline><highlight class="normal"><ref refid="classtf_1_1Taskflow" kindref="compound">tf::Taskflow</ref><sp/>taskflow;</highlight></codeline><codeline><highlight class="normal"><ref refid="classtf_1_1Executor" kindref="compound">tf::Executor</ref><sp/>executor;</highlight></codeline><codeline><highlight class="normal"></highlight></codeline><codeline><highlight class="normal"><ref refid="cpp/atomic/atomic" kindref="compound" external="/home/twhuang/Code/taskflow/doxygen/cppreference-doxygen-web.tag.xml">std::atomic<int></ref><sp/>counter{0};</highlight></codeline><codeline><highlight class="normal"></highlight></codeline><codeline><highlight class="normal">taskflow.<ref refid="classtf_1_1FlowBuilder_1a60d7a666cab71ecfa3010b2efb0d6b57" kindref="member">emplace</ref>([&]<sp/>(<ref refid="classtf_1_1Subflow" kindref="compound">tf::Subflow</ref>&<sp/>sf){</highlight></codeline><codeline><highlight class="normal"><sp/><sp/></highlight><highlight class="keywordflow">for</highlight><highlight class="normal">(</highlight><highlight class="keywordtype">int</highlight><highlight class="normal"><sp/>i=0;<sp/>i<100;<sp/>i++)<sp/>{</highlight></codeline><codeline><highlight class="normal"><sp/><sp/><sp/><sp/>sf.<ref refid="classtf_1_1Subflow_1af9671aa8548882b3425e5a1f10f7a868" kindref="member">silent_async</ref>([&](){<sp/>++counter;<sp/>});</highlight></codeline><codeline><highlight class="normal"><sp/><sp/>}</highlight></codeline><codeline><highlight class="normal"><sp/><sp/>sf.<ref refid="classtf_1_1Subflow_1a59fcac1323e70d920088dd37bd0be245" kindref="member">join</ref>();<sp/><sp/></highlight><highlight class="comment">//<sp/>all<sp/>of<sp/>the<sp/>100<sp/>asynchronous<sp/>tasks<sp/>will<sp/>finish<sp/>by<sp/>this<sp/>join</highlight><highlight class="normal"></highlight></codeline><codeline><highlight class="normal"><sp/><sp/>assert(counter<sp/>==<sp/>100);</highlight></codeline><codeline><highlight class="normal">});</highlight></codeline><codeline><highlight class="normal"></highlight></codeline><codeline><highlight class="normal">executor.<ref refid="classtf_1_1Executor_1a519777f5783981d534e9e53b99712069" kindref="member">run</ref>(taskflow).wait();</highlight></codeline></programlisting></para><para>Creating asynchronous tasks from a subflow allows users to describe, for example, recursive algorithms that define only division without conquering or merging (e.g., parallel quick sort).</para><para><simplesect kind="attention"><para>You should only create asynchronous tasks from a joined subflow. Launching asynchronous tasks from a detached subflow results in undefined behavior.</para></simplesect>Similar to <ref refid="classtf_1_1Executor_1a51acee1670e9f246c7ccd7f6a63f1524" kindref="member">tf::Executor::named_async</ref> and <ref refid="classtf_1_1Executor_1a1febfaa7a99cac8466263c58fd2a7c06" kindref="member">tf::Executor::named_silent_async</ref>, you can name an asynchronous task in <ref refid="classtf_1_1Subflow" kindref="compound">tf::Subflow</ref> to facilitate profiling by using the methods <ref refid="classtf_1_1Subflow_1ae528c2de98ec89afc50b8815c0306b5e" kindref="member">tf::Subflow::named_async</ref> and <ref refid="classtf_1_1Subflow_1a3290b8f729c4511f2023199e4c067951" kindref="member">tf::Subflow::named_silent_async</ref>.</para><para><programlisting filename=".cpp"><codeline><highlight class="normal">taskflow.<ref refid="classtf_1_1FlowBuilder_1a60d7a666cab71ecfa3010b2efb0d6b57" kindref="member">emplace</ref>([](<ref refid="classtf_1_1Subflow" kindref="compound">tf::Subflow</ref>&<sp/>sf){</highlight></codeline><codeline><highlight class="normal"><sp/><sp/><ref refid="classtf_1_1Future" kindref="compound">tf::Future<void></ref><sp/>future<sp/>=<sp/>sf.<ref refid="classtf_1_1Subflow_1ae528c2de98ec89afc50b8815c0306b5e" kindref="member">named_async</ref>(</highlight><highlight class="stringliteral">"name<sp/>of<sp/>the<sp/>task"</highlight><highlight class="normal">,<sp/>[](){});</highlight></codeline><codeline><highlight class="normal"><sp/><sp/>sf.silent_named_async(</highlight><highlight class="stringliteral">"another<sp/>name<sp/>of<sp/>the<sp/>task"</highlight><highlight class="normal">,<sp/>[](){});</highlight></codeline><codeline><highlight class="normal"><sp/><sp/>sf.<ref refid="classtf_1_1Subflow_1a59fcac1323e70d920088dd37bd0be245" kindref="member">join</ref>();</highlight></codeline><codeline><highlight class="normal">});</highlight></codeline></programlisting> </para></sect1></detaileddescription></compounddef></doxygen>
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。