<ahref="#IncludeTheScalablePipelineHeader">Include the Header</a>
</li>
<liclass="level1">
<ahref="#CreateAScalablePipelineModuleTask">Create a Scalable Pipeline Module Task</a>
</li>
<liclass="level1">
<ahref="#ResetAPlaceholderScalablePipeline">Reset a Placeholder Scalable Pipeline</a>
</li>
<liclass="level1">
<ahref="#ScalablePipelineUseOtherIteratorTypes">Use Other Iterator Types</a>
</li>
</ul>
</div>
<divclass="textblock"><p>Unlike <aclass="el" href="classtf_1_1Pipeline.html" title="class to create a pipeline scheduling framework">tf::Pipeline</a> (see <aclass="el" href="TaskParallelPipeline.html">Task-parallel Pipeline</a>) that instantiates all pipes at the construction time, Taskflow provides a scalable alternative called <aclass="el" href="classtf_1_1ScalablePipeline.html" title="class to create a scalable pipeline object">tf::ScalablePipeline</a> to allow variable assignments of pipes using range iterators. A scalable pipeline is thus more flexible for applications to create a pipeline scheduling framework whose pipeline structure depends on runtime variables.</p>
</div><!-- fragment --><h1><aclass="anchor" id="CreateAScalablePipelineModuleTask"></a>
Create a Scalable Pipeline Module Task</h1>
<p>Similar to <aclass="el" href="classtf_1_1Pipeline.html" title="class to create a pipeline scheduling framework">tf::Pipeline</a>, <aclass="el" href="classtf_1_1ScalablePipeline.html" title="class to create a scalable pipeline object">tf::ScalablePipeline</a> is a composable graph object to implement a <em>pipeline scheduling framework</em> in a taskflow. The key difference between <aclass="el" href="classtf_1_1Pipeline.html" title="class to create a pipeline scheduling framework">tf::Pipeline</a> and <aclass="el" href="classtf_1_1ScalablePipeline.html" title="class to create a scalable pipeline object">tf::ScalablePipeline</a> is that a scalable pipeline can accept <em>variable</em> assignments of pipes rather than instantiating all pipes at construction or programming time. Users define a linear range of pipes, each of the same callable type, and apply that range to construct a scalable pipeline. Between successive runs, users can reset the pipeline to a different range of pipes. The following code creates a scalable pipeline that uses four parallel lines to schedule tokens through three serial pipes in the given vector, then resetting that pipeline to a new range of five serial pipes:</p>
<divclass="ttc" id="aclasstf_1_1Executor_html"><divclass="ttname"><ahref="classtf_1_1Executor.html">tf::Executor</a></div><divclass="ttdoc">class to create an executor</div><divclass="ttdef"><b>Definition</b> executor.hpp:62</div></div>
<divclass="ttc" id="aclasstf_1_1Executor_html_a519777f5783981d534e9e53b99712069"><divclass="ttname"><ahref="classtf_1_1Executor.html#a519777f5783981d534e9e53b99712069">tf::Executor::run</a></div><divclass="ttdeci">tf::Future< void > run(Taskflow &taskflow)</div><divclass="ttdoc">runs a taskflow once</div></div>
<divclass="ttc" id="aclasstf_1_1Pipeflow_html"><divclass="ttname"><ahref="classtf_1_1Pipeflow.html">tf::Pipeflow</a></div><divclass="ttdoc">class to create a pipeflow object used by the pipe callable</div><divclass="ttdef"><b>Definition</b> pipeline.hpp:43</div></div>
<divclass="ttc" id="aclasstf_1_1Task_html_a3318a49ff9d0a01cd1e8ee675251e3b7"><divclass="ttname"><ahref="classtf_1_1Task.html#a3318a49ff9d0a01cd1e8ee675251e3b7">tf::Task::dump</a></div><divclass="ttdeci">void dump(std::ostream &ostream) const</div><divclass="ttdoc">dumps the task through an output stream</div><divclass="ttdef"><b>Definition</b> task.hpp:1529</div></div>
<divclass="ttc" id="aclasstf_1_1Task_html_a8c78c453295a553c1c016e4062da8588"><divclass="ttname"><ahref="classtf_1_1Task.html#a8c78c453295a553c1c016e4062da8588">tf::Task::precede</a></div><divclass="ttdeci">Task & precede(Ts &&... tasks)</div><divclass="ttdoc">adds precedence links from this to other tasks</div><divclass="ttdef"><b>Definition</b> task.hpp:1305</div></div>
<divclass="ttc" id="aclasstf_1_1Taskflow_html"><divclass="ttname"><ahref="classtf_1_1Taskflow.html">tf::Taskflow</a></div><divclass="ttdoc">class to create a taskflow object</div><divclass="ttdef"><b>Definition</b> taskflow.hpp:64</div></div>
</div><!-- fragment --><p>The program defines a uniform pipe type of <code>tf::Pipe<std::function<void(tf::Pipeflow&)>></code> and keep all pipes in a vector that is amenable to change. Then, it constructs a scalable pipeline using two range iterators, <code>[first, last)</code>, that point to the beginning and the end of the pipe vector, resulting in a pipeline of three serial stages:</p>
<divclass="dotgraph">
<iframescrolling="no" frameborder="0" src="dot_scalable_pipeline_1.svg" width="376" height="390"><p><b>This browser is not able to show SVG: try Firefox, Chrome, Safari, or Opera instead.</b></p></iframe></div>
<p>Then, the program appends another two pipes into the vector and resets the pipeline to the new range of two additional pipes, resulting in a pipeline of five serial stages:</p>
<divclass="dotgraph">
<iframescrolling="no" frameborder="0" src="dot_scalable_pipeline_2.svg" width="608" height="390"><p><b>This browser is not able to show SVG: try Firefox, Chrome, Safari, or Opera instead.</b></p></iframe></div>
<p>When resetting a scalable pipeline to a new range, it will start from the initial state as if it has just been constructed, i.e., the token number counts from zero.</p>
<dlclass="section note"><dt>Note</dt><dd>Unlike <aclass="el" href="classtf_1_1Pipeline.html" title="class to create a pipeline scheduling framework">tf::Pipeline</a> that keeps the given pipes in a std::tuple object, <aclass="el" href="classtf_1_1ScalablePipeline.html" title="class to create a scalable pipeline object">tf::ScalablePipeline</a> does not own the given pipe but maintains a vector of iterators to each pipe in the given range. It is your responsibility to keep those pipe objects alive during the execution of the pipeline task.</dd></dl>
<p>It is possible to create a scalable pipeline as a placeholder using the constructor <aclass="el" href="classtf_1_1ScalablePipeline.html" title="class to create a scalable pipeline object">tf::ScalablePipeline(size_t num_lines)</a> and reset it to another range later in the application. The following code creates a task to emplace a range of pipes and reset the pipeline to that range, before running the pipeline task:</p>
<divclass="ttc" id="aclasstf_1_1FlowBuilder_html_a4d52a7fe2814b264846a2085e931652c"><divclass="ttname"><ahref="classtf_1_1FlowBuilder.html#a4d52a7fe2814b264846a2085e931652c">tf::FlowBuilder::emplace</a></div><divclass="ttdeci">Task emplace(C &&callable)</div><divclass="ttdoc">creates a static task</div><divclass="ttdef"><b>Definition</b> flow_builder.hpp:1781</div></div>
<divclass="ttc" id="aclasstf_1_1FlowBuilder_html_ac6f22228d4c2ea2e643c4b0d42c0e92a"><divclass="ttname"><ahref="classtf_1_1FlowBuilder.html#ac6f22228d4c2ea2e643c4b0d42c0e92a">tf::FlowBuilder::composed_of</a></div><divclass="ttdeci">Task composed_of(T &object)</div><divclass="ttdoc">creates a module task for the target object</div><divclass="ttdef"><b>Definition</b> flow_builder.hpp:1831</div></div>
<divclass="ttc" id="aclasstf_1_1Pipe_html"><divclass="ttname"><ahref="classtf_1_1Pipe.html">tf::Pipe</a></div><divclass="ttdoc">class to create a pipe object for a pipeline stage</div><divclass="ttdef"><b>Definition</b> pipeline.hpp:144</div></div>
<divclass="ttc" id="aclasstf_1_1Pipeflow_html_a295e5d884665c076f4ef5d78139f7c51"><divclass="ttname"><ahref="classtf_1_1Pipeflow.html#a295e5d884665c076f4ef5d78139f7c51">tf::Pipeflow::token</a></div><divclass="ttdeci">size_t token() const</div><divclass="ttdoc">queries the token identifier</div><divclass="ttdef"><b>Definition</b> pipeline.hpp:78</div></div>
<divclass="ttc" id="aclasstf_1_1Pipeflow_html_a4914c1f381a3016e98285b019cf60d6d"><divclass="ttname"><ahref="classtf_1_1Pipeflow.html#a4914c1f381a3016e98285b019cf60d6d">tf::Pipeflow::pipe</a></div><divclass="ttdeci">size_t pipe() const</div><divclass="ttdoc">queries the pipe identifier of the present token</div><divclass="ttdef"><b>Definition</b> pipeline.hpp:71</div></div>
<divclass="ttc" id="aclasstf_1_1Pipeflow_html_a830b7f204cb87fff17e8d424918d9453"><divclass="ttname"><ahref="classtf_1_1Pipeflow.html#a830b7f204cb87fff17e8d424918d9453">tf::Pipeflow::stop</a></div><divclass="ttdeci">void stop()</div><divclass="ttdoc">stops the pipeline scheduling</div><divclass="ttdef"><b>Definition</b> pipeline.hpp:88</div></div>
<divclass="ttc" id="aclasstf_1_1ScalablePipeline_html"><divclass="ttname"><ahref="classtf_1_1ScalablePipeline.html">tf::ScalablePipeline</a></div><divclass="ttdoc">class to create a scalable pipeline object</div><divclass="ttdef"><b>Definition</b> pipeline.hpp:775</div></div>
<divclass="ttc" id="aclasstf_1_1Task_html"><divclass="ttname"><ahref="classtf_1_1Task.html">tf::Task</a></div><divclass="ttdoc">class to create a task handle over a taskflow node</div><divclass="ttdef"><b>Definition</b> task.hpp:569</div></div>
<divclass="ttc" id="aclasstf_1_1Task_html_a08ada0425b490997b6ff7f310107e5e3"><divclass="ttname"><ahref="classtf_1_1Task.html#a08ada0425b490997b6ff7f310107e5e3">tf::Task::name</a></div><divclass="ttdeci">const std::string & name() const</div><divclass="ttdoc">queries the name of the task</div><divclass="ttdef"><b>Definition</b> task.hpp:1435</div></div>
<divclass="ttc" id="aclasstf_1_1Task_html_a331b1b726555072e7c7d10941257f664"><divclass="ttname"><ahref="classtf_1_1Task.html#a331b1b726555072e7c7d10941257f664">tf::Task::succeed</a></div><divclass="ttdeci">Task & succeed(Ts &&... tasks)</div><divclass="ttdoc">adds precedence links from other tasks to this</div><divclass="ttdef"><b>Definition</b> task.hpp:1313</div></div>
</div><!-- fragment --><p>The task graph of this program is shown below:</p>
<divclass="dotgraph">
<iframescrolling="no" frameborder="0" src="dot_scalable_pipeline_3.svg" width="1142" height="252"><p><b>This browser is not able to show SVG: try Firefox, Chrome, Safari, or Opera instead.</b></p></iframe></div>
<dlclass="section note"><dt>Note</dt><dd>It is your responsibility to ensure a scalable pipeline has a valid structure before running it. A valid pipeline must have at least one parallel line and one pipe, where the first pipe is a serial type.</dd></dl>
<p>Similarly, you can create an empty scalable pipeline using the default constructor <aclass="el" href="classtf_1_1ScalablePipeline.html" title="class to create a scalable pipeline object">tf::ScalablePipeline()</a> and reset it later in your program.</p>
<divclass="ttc" id="aclasstf_1_1ScalablePipeline_html_a940a8de7b53ac5cbd59c55091d88c88f"><divclass="ttname"><ahref="classtf_1_1ScalablePipeline.html#a940a8de7b53ac5cbd59c55091d88c88f">tf::ScalablePipeline::reset</a></div><divclass="ttdeci">void reset()</div><divclass="ttdoc">resets the pipeline</div><divclass="ttdef"><b>Definition</b> pipeline.hpp:1084</div></div>
</div><!-- fragment --><h1><aclass="anchor" id="ScalablePipelineUseOtherIteratorTypes"></a>
Use Other Iterator Types</h1>
<p>When assigning a range to a scalable pipeline, the pipeline fetches all pipe iterators in that range to an internal vector. This organization allows invoking a pipe callable to be a random accessible operation, regardless of the pipe container type. Taskflow does not have much restriction on the iterator type, as long as these pipes can be iterated in a sequential order using the postfix increment operator, <code>++</code>.</p>
<divclass="fragment"><divclass="line"><spanclass="comment">// use vector to store pipes</span></div>