3#include "flow_builder.hpp"
66 friend class Topology;
67 friend class Executor;
68 friend class FlowBuilder;
73 std::stack<std::tuple<const Node*, const Graph*, size_t>> stack;
74 std::unordered_map<const Graph*, size_t> visited;
184 void dump(std::ostream& ostream)
const;
192 std::string
dump()
const;
243 void name(
const std::string&);
253 const std::string&
name()
const;
277 template <
typename V>
326 mutable std::mutex _mutex;
332 std::queue<std::shared_ptr<Topology>> _topologies;
334 void _dump(std::ostream&,
const Graph*)
const;
335 void _dump(std::ostream&,
const Node*, Dumper&,
size_t level)
const;
336 void _dump(std::ostream&,
const Graph*, Dumper&,
size_t level)
const;
338 size_t _fetch_enqueue(std::shared_ptr<Topology>);
343 FlowBuilder {_graph},
353 std::scoped_lock<std::mutex> lock(rhs._mutex);
354 _name = std::move(rhs._name);
355 _graph = std::move(rhs._graph);
356 _topologies = std::move(rhs._topologies);
362 std::scoped_lock<std::mutex, std::mutex> lock(_mutex, rhs._mutex);
363 _name = std::move(rhs._name);
364 _graph = std::move(rhs._graph);
365 _topologies = std::move(rhs._topologies);
377 return _graph.size();
382 return _graph.empty();
403 for(
auto itr = _graph.begin(); itr != _graph.end(); ++itr) {
411 from._node->_remove_successors(to._node);
414 to._node->_remove_predecessors(from._node);
418inline size_t Taskflow::_fetch_enqueue(std::shared_ptr<Topology> tpg) {
419 std::lock_guard<std::mutex> lock(_mutex);
420 auto pre_size = _topologies.size();
421 _topologies.emplace(std::move(tpg));
427 std::ostringstream oss;
434 os <<
"digraph Taskflow {\n";
435 os <<
" compound=true;\n";
441inline void Taskflow::_dump(std::ostream& os,
const Graph* top)
const {
446 dumper.stack.push({
nullptr, top, 1});
447 dumper.visited[top] = dumper.id++;
449 while(!dumper.stack.empty()) {
451 auto [p, f, depth] = dumper.stack.top();
454 std::string ind(depth * 2,
' ');
455 std::string ind2((depth + 1) * 2,
' ');
457 os << ind <<
"subgraph cluster_p" << f <<
" {\n";
458 os << ind2 <<
"label=\"";
462 if (p->_name.empty()) os <<
'm' << dumper.visited[f];
463 else os << p->name();
468 if(_name.empty()) os <<
'p' <<
this;
474 _dump(os, f, dumper, depth + 1);
480inline void Taskflow::_dump(
481 std::ostream& os,
const Node* node, Dumper& dumper,
size_t level
484 std::string ind(level * 2,
' ');
487 os << ind <<
'p' << node <<
"[label=\"";
488 if(node->_name.empty()) os <<
'p' << node;
489 else os << node->_name;
491#ifdef TF_ENABLE_TASK_PRIORITY
493 switch (node->priority()) {
494 case 0: os <<
"\\npriority: HIGH";
break;
495 case 1: os <<
"\\npriority: NORMAL";
break;
496 case 2: os <<
"\\npriority: LOW";
break;
503 switch(node->_handle.index()) {
505 case Node::CONDITION:
506 case Node::MULTI_CONDITION:
507 os <<
"shape=diamond color=black fillcolor=aquamarine style=filled";
516 for(
size_t s=0; s<node->_num_successors; ++s) {
517 if(node->_is_conditioner()) {
518 os << ind <<
'p' << node <<
" -> p" << node->_edges[s]
519 <<
" [style=dashed label=\"" << s <<
"\"];\n";
521 os << ind <<
'p' << node <<
" -> p" << node->_edges[s] <<
";\n";
526 switch(
auto hid = node->_handle.index(); hid) {
529 case Node::ADOPTED_MODULE: {
531 auto& g = (hid == Node::SUBFLOW) ?
532 std::get_if<Node::Subflow>(&node->_handle)->subgraph :
533 std::get_if<Node::AdoptedModule>(&node->_handle)->graph;
536 std::string ind2((level + 1) * 2,
' ');
538 os << ind <<
"subgraph cluster_p" << node <<
" {\n";
539 os << ind2 << ((hid == Node::SUBFLOW) ?
"label=\"Subflow: "
540 :
"label=\"AdoptedModule: ");
541 if(node->_name.empty()) os <<
'p' << node;
542 else os << node->_name;
544 os << ind2 <<
"color=blue;\n";
546 _dump(os, &g, dumper, level + 1);
551 auto first = *g.begin();
552 os << ind <<
'p' << first <<
" -> p" << node
553 <<
" [ltail=cluster_p" << node
554 <<
" style=dashed color=blue];\n";
565inline void Taskflow::_dump(
566 std::ostream& os,
const Graph* graph, Dumper& dumper,
size_t level
569 std::string ind(level * 2,
' ');
571 for(
auto itr =
graph->begin(); itr !=
graph->end(); ++itr) {
576 if(n->_handle.index() != Node::MODULE) {
577 _dump(os, n, dumper, level);
581 auto mgraph = &(std::get_if<Node::Module>(&n->_handle)->graph);
583 os << ind <<
'p' << n <<
"[shape=box3d, color=blue, label=\"";
584 if(n->_name.empty()) os <<
'p' << n;
587 if(dumper.visited.find(mgraph) == dumper.visited.end()) {
588 dumper.visited[mgraph] = dumper.id++;
589 dumper.stack.push({n, mgraph, level});
592 if(n->_name.empty()) os <<
" [m" << dumper.visited[mgraph] <<
"]";
595 for(
size_t i=0; i<n->_num_successors; ++i) {
596 os << ind <<
'p' << n <<
" -> " <<
'p' << n->_edges[i] <<
";\n";
642 friend class Executor;
643 friend class Subflow;
644 friend class Runtime;
714 std::weak_ptr<Topology> _topology;
716 Future(std::future<T>&&, std::weak_ptr<Topology>);
721 std::future<T> {std::move(f)},
722 _topology {std::move(p)} {
732 if(
auto ptr = _topology.lock(); ptr) {
733 ptr->_estate.fetch_or(ESTATE::CANCELLED, std::memory_order_relaxed);
bool cancel()
cancels the execution of the running taskflow associated with this future object
Definition taskflow.hpp:731
Future & operator=(const Future &)=delete
disabled copy assignment
Future()=default
default constructor
Future(const Future &)=delete
disabled copy constructor
Future(Future &&)=default
default move constructor
class to create a graph object
Definition graph.hpp:47
class to create a task handle over a taskflow node
Definition task.hpp:569
void clear()
clears the associated task dependency graph
Definition taskflow.hpp:371
bool empty() const
queries if this taskflow is empty (has no tasks)
Definition taskflow.hpp:381
void remove_dependency(Task from, Task to)
removes dependencies that go from task from to task to
Definition taskflow.hpp:409
void for_each_task(V &&visitor) const
applies a visitor to each task in this taskflow
Definition taskflow.hpp:402
Taskflow(const std::string &name)
constructs a taskflow with the given name
Definition taskflow.hpp:342
Graph & graph()
returns a reference to the underlying graph object
Definition taskflow.hpp:396
const std::string & name() const
queries the name of this taskflow
Definition taskflow.hpp:391
std::string dump() const
dumps the taskflow to a std::string of DOT format
Definition taskflow.hpp:426
Taskflow & operator=(Taskflow &&rhs)
move assignment operator
Definition taskflow.hpp:360
~Taskflow()=default
default destructor
void name(const std::string &)
assigns a new name to this taskflow
Definition taskflow.hpp:386
Taskflow()
constructs a taskflow
Definition taskflow.hpp:348
size_t num_tasks() const
queries the number of tasks in this taskflow
Definition taskflow.hpp:376
taskflow namespace
Definition small_vector.hpp:20