4 #include "framework.hpp" 19 template <
template <
typename...>
typename E>
22 using StaticWork =
typename Node::StaticWork;
23 using DynamicWork =
typename Node::DynamicWork;
29 Closure(
const Closure&) =
default;
32 Closure& operator = (
const Closure&) =
default;
34 void operator ()()
const;
104 template <
typename C>
165 void _schedule(Node&);
174 template <
template <
typename...>
typename E>
176 taskflow{&t}, node {&n} {
180 template <
template <
typename...>
typename E>
187 const auto num_successors = node->num_successors();
191 if(
auto index=node->_work.index(); index == 0) {
192 if(
auto &f = std::get<StaticWork>(node->_work); f !=
nullptr){
199 bool first_time {
false};
202 if(!(node->_subgraph)){
203 node->_subgraph.emplace();
209 std::invoke(std::get<DynamicWork>(node->_work), fb);
212 if(first_time && !(node->_subgraph->empty())) {
237 for(
auto n = node->_subgraph->begin(); n != node->_subgraph->end(); ++n) {
238 n->_topology = node->_topology;
239 if(n->num_successors() == 0) {
240 n->precede(fb.detached() ? node->_topology->_target : *node);
242 if(n->num_dependents() == 0) {
243 src.emplace_back(&(*n));
248 taskflow->_schedule(*n);
259 for(
size_t i=0; i<num_successors; ++i) {
260 if(--(node->_successors[i]->_dependents) == 0) {
261 taskflow->_schedule(*(node->_successors[i]));
271 template <
template <
typename...>
typename E>
278 template <
template <
typename...>
typename E>
281 _executor {std::make_shared<Executor>(N)} {
285 template <
template <
typename...>
typename E>
288 _executor {std::move(e)} {
290 if(_executor ==
nullptr) {
291 TF_THROW(Error::EXECUTOR,
292 "failed to construct taskflow (executor cannot be null)" 298 template <
template <
typename...>
typename E>
304 template <
template <
typename...>
typename E>
306 return _graph.size();
310 template <
template <
typename...>
typename E>
312 return _executor->num_workers();
316 template <
template <
typename...>
typename E>
318 return std::distance(_topologies.begin(), _topologies.end());
322 template <
template <
typename...>
typename E>
328 template <
template <
typename...>
typename E>
331 if(_graph.empty())
return;
333 auto& topology = _topologies.emplace_front(std::move(_graph));
335 _schedule(topology._sources);
340 template <
template <
typename...>
typename E>
341 template <
typename C>
349 auto& topology = _topologies.emplace_front(std::move(_graph), std::forward<C>(c));
351 _schedule(topology._sources);
355 template <
template <
typename...>
typename E>
359 return std::async(std::launch::deferred, [](){}).share();
362 auto& topology = _topologies.emplace_front(std::move(_graph));
364 _schedule(topology._sources);
366 return topology._future;
371 template <
template <
typename...>
typename E>
372 template <
typename C>
377 return std::async(std::launch::deferred, [](){}).share();
380 auto& topology = _topologies.emplace_front(std::move(_graph), std::forward<C>(c));
382 _schedule(topology._sources);
384 return topology._future;
388 template <
template <
typename...>
typename E>
390 if(!_graph.empty()) {
397 template <
template <
typename...>
typename E>
399 for(
auto& t: _topologies){
408 template <
template <
typename...>
typename E>
410 _executor->emplace(*
this, node);
417 template <
template <
typename...>
typename E>
420 closures.reserve(nodes.size());
421 for(
auto src : nodes) {
422 closures.emplace_back(*
this, *src);
424 _executor->batch(std::move(closures));
428 template <
template <
typename...>
typename E>
433 for(
const auto& tpg : _topologies) {
441 template <
template <
typename...>
typename E>
443 for(
const auto& tpg : _topologies) {
449 template <
template <
typename...>
typename E>
452 os <<
"digraph Taskflow {\n";
454 for(
const auto& node : _graph) {
464 template <
template <
typename...>
typename E>
The base class to derive a taskflow class.
Definition: basic_taskflow.hpp:20
std::shared_ptr< Executor > share_executor()
shares ownership of the executor associated with this taskflow object
Definition: basic_taskflow.hpp:323
size_t num_nodes() const
queries the number of nodes in the present task dependency graph
Definition: basic_taskflow.hpp:305
std::shared_future< void > dispatch()
dispatches the present graph to threads and returns immediately
Definition: basic_taskflow.hpp:356
Definition: taskflow.hpp:6
void silent_dispatch()
dispatches the present graph to threads and returns immediately
Definition: basic_taskflow.hpp:329
T hardware_concurrency(T... args)
BasicTaskflow()
constructs the taskflow with std::thread::hardware_concurrency worker threads
Definition: basic_taskflow.hpp:272
The building blocks of dynamic tasking.
Definition: flow_builder.hpp:713
size_t num_topologies() const
queries the number of existing topologies
Definition: basic_taskflow.hpp:317
void wait_for_topologies()
blocks until all running topologies complete and then cleans up all associated storages ...
Definition: basic_taskflow.hpp:398
void wait_for_all()
dispatches the present graph to threads and wait for all topologies to complete
Definition: basic_taskflow.hpp:389
The building blocks of task dependency graphs.
Definition: flow_builder.hpp:13
size_t num_workers() const
queries the number of worker threads in the associated executor
Definition: basic_taskflow.hpp:311
E< Closure > Executor
alias of executor type
Definition: basic_taskflow.hpp:47
~BasicTaskflow()
destructs the taskflow
Definition: basic_taskflow.hpp:299
std::string dump() const
dumps the present task dependency graph in DOT format to a std::string
Definition: basic_taskflow.hpp:465
std::string dump_topologies() const
dumps the existing topologies in DOT format to a std::string
Definition: basic_taskflow.hpp:429