Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include "dag.h"
00036
00037 #include "perf/perf.h"
00038
00039
00040
00041 namespace graph {
00042
00043
00044 DAG::~DAG(void) throw() { }
00045
00046
00047 typedef std::map<std::string, smart_ptr<SetString> > map_set_t;
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063 class DagImpl : public DAG {
00064 public:
00065 ~DagImpl(void) throw() { }
00066
00067
00068 void initialize(void) throw() { }
00069
00070
00071 void addNode(IN const char * node);
00072 void addEdge(IN const char * from_node,
00073 IN const char * to_node);
00074 void getOrderedNodeList(OUT VecString& leaf_to_root) const;
00075
00076 private:
00077
00078 SetString * getSet(IN const char * node);
00079
00080
00081 map_set_t m_map;
00082 SetString m_allNodes;
00083 };
00084
00085
00086
00087 void
00088 DagImpl::addNode
00089 (
00090 IN const char * node
00091 )
00092 {
00093 ASSERT(node, "null");
00094
00095 m_allNodes.insert(node);
00096 }
00097
00098
00099
00100 void
00101 DagImpl::addEdge
00102 (
00103 IN const char * from_node,
00104 IN const char * to_node
00105 )
00106 {
00107 ASSERT(from_node, "null from_node in DAG::addEdge()");
00108 ASSERT(to_node, "null to_node in DAG::addEdge()");
00109
00110
00111 SetString * set = this->getSet(from_node);
00112 ASSERT(set, "getSet() should always return non-null");
00113
00114 set->insert(to_node);
00115
00116
00117 this->addNode(from_node);
00118 this->addNode(to_node);
00119 }
00120
00121
00122
00123 void
00124 DagImpl::getOrderedNodeList
00125 (
00126 OUT VecString& leaf_to_root
00127 )
00128 const
00129 {
00130 perf::Timer timer("DAG::getOrderedNodeList");
00131
00132
00133 leaf_to_root.clear();
00134
00135
00136 SetString visited;
00137 SetString remaining;
00138 for (SetString::const_iterator i = m_allNodes.begin();
00139 i != m_allNodes.end(); ++i) {
00140
00141 if (m_map.end() == m_map.find(*i)) {
00142 visited.insert(*i);
00143 leaf_to_root.push_back(*i);
00144 } else {
00145 remaining.insert(*i);
00146 }
00147 }
00148 ASSERT(visited.size() > 0, "No leaf nodes? Cyclical dependency");
00149
00150
00151 if (0 == remaining.size())
00152 return;
00153
00154
00155 for (long depth = 1; true; ++depth) {
00156
00157
00158
00159
00160 VecString nuke;
00161 for (SetString::const_iterator i = remaining.begin();
00162 i != remaining.end(); ++i) {
00163 if (visited.end() != visited.find(*i)) {
00164 continue;
00165 }
00166
00167
00168 map_set_t::const_iterator j = m_map.find(*i);
00169 ASSERT(m_map.end() != j,
00170 "not a leaf, must have set! '%s'", i->c_str());
00171 const SetString * set = j->second;
00172 ASSERT(set, "null set in map?");
00173
00174 bool all_children_visited = true;
00175 for (SetString::const_iterator k = set->begin();
00176 k != set->end(); ++k) {
00177 if (visited.end() == visited.find(*k)) {
00178 all_children_visited = false;
00179 break;
00180 }
00181 }
00182
00183 if (!all_children_visited)
00184 continue;
00185
00186
00187 visited.insert(*i);
00188 nuke.push_back(*i);
00189 leaf_to_root.push_back(*i);
00190 }
00191 ASSERT(nuke.size() > 0, "cyclical dependency?");
00192
00193
00194 for (VecString::iterator i = nuke.begin(); i != nuke.end(); ++i)
00195 {
00196 remaining.erase(remaining.find(*i));
00197 }
00198
00199 if (0 == remaining.size())
00200 break;
00201 }
00202 }
00203
00204
00205
00206 SetString *
00207 DagImpl::getSet
00208 (
00209 IN const char * node
00210 )
00211 {
00212 ASSERT(node, "null node in getSet()");
00213
00214 map_set_t::iterator i = m_map.find(node);
00215 if (m_map.end() == i) {
00216 smart_ptr<SetString> set = new SetString;
00217 ASSERT(set, "out of memory");
00218 m_map[node] = set;
00219 return set;
00220 } else {
00221 return i->second;
00222 }
00223 }
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233 smart_ptr<DAG>
00234 DAG::create
00235 (
00236 void
00237 )
00238 {
00239 smart_ptr<DagImpl> local = new DagImpl;
00240 ASSERT(local, "out of memory");
00241
00242 local->initialize();
00243
00244 return local;
00245 }
00246
00247
00248
00249 };
00250