28enum eCyclicCheckVisitedState {
43struct CyclesSolverState {
47 if (num_cycles != 0) {
48 printf(
"Detected %d dependency cycles\n", num_cycles);
56inline void set_node_visited_state(
Node *
node, eCyclicCheckVisitedState
state)
61inline eCyclicCheckVisitedState get_node_visited_state(
Node *
node)
66inline void set_node_num_visited_children(
Node *
node,
int num_children)
71inline int get_node_num_visited_children(
Node *
node)
76void schedule_node_to_stack(CyclesSolverState *
state, OperationNode *
node)
81 entry.via_relation =
nullptr;
82 state->traversal_stack.push(entry);
83 set_node_visited_state(
node, NODE_IN_STACK);
87void schedule_leaf_nodes(CyclesSolverState *
state)
90 bool has_inlinks =
false;
91 for (Relation *rel :
node->inlinks) {
97 if (has_inlinks ==
false) {
101 set_node_visited_state(
node, NODE_NOT_VISITED);
109bool schedule_non_checked_node(CyclesSolverState *
state)
112 if (get_node_visited_state(
node) == NODE_NOT_VISITED) {
120bool check_relation_can_murder(Relation *relation)
128Relation *select_relation_to_murder(Relation *relation, StackEntry *cycle_start_entry)
134 if (check_relation_can_murder(relation)) {
137 StackEntry *current = cycle_start_entry;
138 OperationNode *to_node = (OperationNode *)relation->to;
139 while (current->node != to_node) {
140 if (check_relation_can_murder(current->via_relation)) {
141 return current->via_relation;
143 current = current->from;
149void solve_cycles(CyclesSolverState *
state)
154 OperationNode *
node = entry->node;
155 bool all_child_traversed =
true;
156 const int num_visited = get_node_num_visited_children(
node);
160 OperationNode *to = (OperationNode *)rel->to;
161 eCyclicCheckVisitedState to_state = get_node_visited_state(to);
162 if (to_state == NODE_IN_STACK) {
163 std::string cycle_str =
" " + to->full_identifier() +
" depends on\n " +
165 StackEntry *current = entry;
166 while (current->node != to) {
168 cycle_str +=
" " + current->from->node->full_identifier() +
" via '" +
169 current->via_relation->name +
"'\n";
170 current = current->from;
172 printf(
"Dependency cycle detected:\n%s", cycle_str.c_str());
173 Relation *sacrificial_relation = select_relation_to_murder(rel, entry);
177 else if (to_state == NODE_NOT_VISITED) {
178 StackEntry new_entry;
180 new_entry.from = entry;
181 new_entry.via_relation = rel;
183 set_node_visited_state(
node, NODE_IN_STACK);
184 all_child_traversed =
false;
185 set_node_num_visited_children(
node, i);
190 if (all_child_traversed) {
191 set_node_visited_state(
node, NODE_VISITED);
203 schedule_leaf_nodes(&
state);
204 solve_cycles(&
state);
209 while (schedule_non_checked_node(&
state)) {
210 solve_cycles(&
state);
Stack< StackEntry > traversal_stack
void deg_graph_detect_cycles(Depsgraph *graph)
std::string full_identifier() const