mirror of
https://git.rwth-aachen.de/acs/public/villas/node/
synced 2025-03-16 00:00:02 +01:00
108 lines
2.3 KiB
C++
108 lines
2.3 KiB
C++
![]() |
#ifndef VILLAS_DEPENDENCY_GRAPH_HPP
|
||
|
#error "Do not include this file directly, please include depedency_graph.hpp"
|
||
|
#endif
|
||
|
|
||
|
#include "dependency_graph.hpp"
|
||
|
#include <sstream>
|
||
|
|
||
|
namespace villas {
|
||
|
namespace utils {
|
||
|
|
||
|
template<typename T>
|
||
|
bool
|
||
|
DependencyGraph<T>::addNode(const T &node)
|
||
|
{
|
||
|
bool existedBefore = nodeExists(node);
|
||
|
|
||
|
// accessing is enough to create if not exists
|
||
|
graph[node];
|
||
|
|
||
|
return existedBefore;
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
void
|
||
|
DependencyGraph<T>::removeNode(const T &node)
|
||
|
{
|
||
|
graph.erase(node);
|
||
|
|
||
|
// check if other nodes depend on this one
|
||
|
for(auto& [key, dependencies] : graph) {
|
||
|
if(nodeInList(dependencies, node)) {
|
||
|
// remove other node that depends on the one to delete
|
||
|
removeNode(key);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
void
|
||
|
DependencyGraph<T>::addDependency(const T &node, const T &dependency)
|
||
|
{
|
||
|
NodeList& dependencies = graph[node];
|
||
|
if(not nodeInList(dependencies, dependency))
|
||
|
dependencies.push_back(dependency);
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
void
|
||
|
DependencyGraph<T>::dump() {
|
||
|
for(auto& node : graph) {
|
||
|
std::stringstream ss;
|
||
|
for(auto& dep : node.second) {
|
||
|
ss << dep << " ";
|
||
|
}
|
||
|
cpp_debug << node.first << ": " << ss.str();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
typename DependencyGraph<T>::NodeList
|
||
|
DependencyGraph<T>::getEvaluationOrder() const
|
||
|
{
|
||
|
// copy graph to preserve information (we have to delete entries later)
|
||
|
Graph graph = this->graph;
|
||
|
|
||
|
// output list
|
||
|
NodeList out;
|
||
|
|
||
|
while(graph.size() > 0) {
|
||
|
int added = 0;
|
||
|
|
||
|
// look for nodes with no dependencies
|
||
|
for(auto& [key, dependencies] : graph) {
|
||
|
|
||
|
for(auto dep = dependencies.begin(); dep != dependencies.end(); ++dep) {
|
||
|
if(nodeInList(out, *dep)) {
|
||
|
// dependency has been pushed to list in last round
|
||
|
dep = dependencies.erase(dep);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// nodes with no dependencies can be pushed to list
|
||
|
if(dependencies.empty()) {
|
||
|
out.push_back(key);
|
||
|
graph.erase(key);
|
||
|
added++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// if a round doesn't add any elements and is not the last, then
|
||
|
// there is a circular dependency
|
||
|
if(added == 0 and graph.size() > 0) {
|
||
|
cpp_error << "Circular dependency detected! IPs not available:";
|
||
|
Logger::Indenter indent = cpp_debug.indent();
|
||
|
for(auto& [key, value] : graph) {
|
||
|
cpp_error << key;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return out;
|
||
|
}
|
||
|
|
||
|
} // namespace utils
|
||
|
} // namespace villas
|