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;
493 switch(node->_handle.index()) {
495 case Node::CONDITION:
496 case Node::MULTI_CONDITION:
497 os <<
"shape=diamond color=black fillcolor=aquamarine style=filled";
506 for(
size_t s=0; s<node->_num_successors; ++s) {
507 if(node->_is_conditioner()) {
508 os << ind <<
'p' << node <<
" -> p" << node->_edges[s]
509 <<
" [style=dashed label=\"" << s <<
"\"];\n";
511 os << ind <<
'p' << node <<
" -> p" << node->_edges[s] <<
";\n";
516 switch(
auto hid = node->_handle.index(); hid) {
519 case Node::ADOPTED_MODULE: {
521 auto& g = (hid == Node::SUBFLOW) ?
522 std::get_if<Node::Subflow>(&node->_handle)->subgraph :
523 std::get_if<Node::AdoptedModule>(&node->_handle)->graph;
526 std::string ind2((level + 1) * 2,
' ');
528 os << ind <<
"subgraph cluster_p" << node <<
" {\n";
529 os << ind2 << ((hid == Node::SUBFLOW) ?
"label=\"Subflow: "
530 :
"label=\"AdoptedModule: ");
531 if(node->_name.empty()) os <<
'p' << node;
532 else os << node->_name;
534 os << ind2 <<
"color=blue;\n";
536 _dump(os, &g, dumper, level + 1);
541 auto first = *g.begin();
542 os << ind <<
'p' << first <<
" -> p" << node
543 <<
" [ltail=cluster_p" << node
544 <<
" style=dashed color=blue];\n";
555inline void Taskflow::_dump(
556 std::ostream& os,
const Graph* graph, Dumper& dumper,
size_t level
559 std::string ind(level * 2,
' ');
561 for(
auto itr =
graph->begin(); itr !=
graph->end(); ++itr) {
566 if(n->_handle.index() != Node::MODULE) {
567 _dump(os, n, dumper, level);
571 auto mgraph = &(std::get_if<Node::Module>(&n->_handle)->graph);
573 os << ind <<
'p' << n <<
"[shape=box3d, color=blue, label=\"";
574 if(n->_name.empty()) os <<
'p' << n;
577 if(dumper.visited.find(mgraph) == dumper.visited.end()) {
578 dumper.visited[mgraph] = dumper.id++;
579 dumper.stack.push({n, mgraph, level});
582 if(n->_name.empty()) os <<
" [m" << dumper.visited[mgraph] <<
"]";
585 for(
size_t i=0; i<n->_num_successors; ++i) {
586 os << ind <<
'p' << n <<
" -> " <<
'p' << n->_edges[i] <<
";\n";
632 friend class Executor;
633 friend class Subflow;
634 friend class Runtime;
704 std::weak_ptr<Topology> _topology;
706 Future(std::future<T>&&, std::weak_ptr<Topology>);
711 std::future<T> {std::move(f)},
712 _topology {std::move(p)} {
722 if(
auto ptr = _topology.lock(); ptr) {
723 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:721
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:263
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