Files
textmate/Shared/include/oak/dependency_graph.h
Allan Odgaard 9894969e67 Initial commit
2012-08-09 16:25:56 +02:00

85 lines
1.9 KiB
C++

#ifndef DEPENDENCY_GRAPH_H_A254DOQ
#define DEPENDENCY_GRAPH_H_A254DOQ
namespace oak
{
struct dependency_graph
{
// a node is an integer and represents a task to perform
void add_node (size_t node)
{
dependencies.insert(std::make_pair(node, std::set<size_t>()));
}
// an edge establishes a dependency from one node (first argument) to another (second argument)
// e.g. if node RUN depends on node BUILD we call: add_edge(RUN, NODE)
void add_edge (size_t node, size_t dependsOn)
{
dependencies[node].insert(dependsOn);
}
// mark a node as “modified” and return all nodes which in effect are then also modified
std::set<size_t> touch (size_t node) const
{
std::set<size_t> res;
std::vector<size_t> active(1, node);
while(!active.empty())
{
size_t n = active.back();
res.insert(n);
active.pop_back();
iterate(it, dependencies)
{
std::set<size_t>::const_iterator node = it->second.find(n);
if(node == it->second.end() || res.find(it->first) != res.end())
continue;
active.push_back(it->first);
}
}
return res;
}
// return list of all nodes ordered so that for each node, all it depends on is before that node in this list
std::vector<size_t> topological_order () const
{
std::vector<size_t> res, active;
iterate(it, dependencies)
{
if(it->second.empty())
active.push_back(it->first);
}
std::map< size_t, std::set<size_t> > tmp = dependencies;
while(!active.empty())
{
size_t n = active.back();
res.push_back(n);
active.pop_back();
iterate(it, tmp)
{
std::set<size_t>::const_iterator node = it->second.find(n);
if(node == it->second.end())
continue;
it->second.erase(node);
if(it->second.empty())
active.push_back(it->first);
}
}
return res;
}
private:
std::map< size_t, std::set<size_t> > dependencies;
};
} /* oak */
#endif /* end of include guard: DEPENDENCY_GRAPH_H_A254DOQ */