Files
textmate/Shared/include/oak/dependency_graph.h
2014-04-14 14:26:52 +07: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.emplace(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();
for(auto const& 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;
for(auto const& 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();
for(auto& 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 */