Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(338)

Side by Side Diff: chrome/browser/profiles/dependency_graph.cc

Issue 13454032: Extract DependencyGraph from ProfileDependencyManager. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: no void* Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/profiles/dependency_graph.h"
6
7 #include <algorithm>
8 #include <deque>
9 #include <iterator>
10
11 DependencyGraph::DependencyGraph(const GetNodeNameCallback& callback)
12 : get_node_name_callback_(callback) {
13 }
14
15 DependencyGraph::~DependencyGraph() {
16 }
17
18 void DependencyGraph::AddNode(DependencyNode* node) {
19 all_nodes_.push_back(node);
20 construction_order_.clear();
21 }
22
23 void DependencyGraph::RemoveNode(DependencyNode* node) {
24 all_nodes_.erase(std::remove(all_nodes_.begin(),
25 all_nodes_.end(),
26 node),
27 all_nodes_.end());
28
29 // Remove all dependency edges that contain this node.
30 EdgeMap::iterator it = edges_.begin();
31 while (it != edges_.end()) {
32 EdgeMap::iterator temp = it;
33 ++it;
34
35 if (temp->first == node || temp->second == node)
36 edges_.erase(temp);
37 }
38
39 construction_order_.clear();
40 }
41
42 void DependencyGraph::AddEdge(DependencyNode* depended,
43 DependencyNode* dependee) {
44 edges_.insert(std::make_pair(depended, dependee));
45 construction_order_.clear();
46 }
47
48 bool DependencyGraph::GetConstructionOrder(
49 std::vector<DependencyNode*>* order) {
50 if (construction_order_.empty() && !BuildConstructionOrder())
51 return false;
52
53 *order = construction_order_;
54 return true;
55 }
56
57 bool DependencyGraph::GetDestructionOrder(
58 std::vector<DependencyNode*>* order) {
59 if (construction_order_.empty() && !BuildConstructionOrder())
60 return false;
61
62 *order = construction_order_;
63
64 // Destroy nodes in reverse order.
65 std::reverse(order->begin(), order->end());
66
67 return true;
68 }
69
70 bool DependencyGraph::BuildConstructionOrder() {
71 // Step 1: Build a set of nodes with no incoming edges.
72 std::deque<DependencyNode*> queue;
73 std::copy(all_nodes_.begin(),
74 all_nodes_.end(),
75 std::back_inserter(queue));
76
77 std::deque<DependencyNode*>::iterator queue_end = queue.end();
78 for (EdgeMap::const_iterator it = edges_.begin();
79 it != edges_.end(); ++it) {
80 queue_end = std::remove(queue.begin(), queue_end, it->second);
81 }
82 queue.erase(queue_end, queue.end());
83
84 // Step 2: Do the Kahn topological sort.
85 std::vector<DependencyNode*> output;
86 EdgeMap edges(edges_);
87 while (!queue.empty()) {
88 DependencyNode* node = queue.front();
89 queue.pop_front();
90 output.push_back(node);
91
92 std::pair<EdgeMap::iterator, EdgeMap::iterator> range =
93 edges.equal_range(node);
94 EdgeMap::iterator it = range.first;
95 while (it != range.second) {
96 DependencyNode* dest = it->second;
97 EdgeMap::iterator temp = it;
98 it++;
99 edges.erase(temp);
100
101 bool has_incoming_edges = false;
102 for (EdgeMap::iterator jt = edges.begin(); jt != edges.end(); ++jt) {
103 if (jt->second == dest) {
104 has_incoming_edges = true;
105 break;
106 }
107 }
108
109 if (!has_incoming_edges)
110 queue.push_back(dest);
111 }
112 }
113
114 if (!edges.empty()) {
115 // Dependency graph has a cycle.
116 return false;
117 }
118
119 construction_order_ = output;
120 return true;
121 }
122
123 std::string DependencyGraph::DumpAsGraphviz(const std::string& toplevel_name) {
124 std::string result("digraph {\n");
125
126 // Make a copy of all nodes.
127 std::deque<DependencyNode*> nodes;
128 std::copy(all_nodes_.begin(), all_nodes_.end(), std::back_inserter(nodes));
129
130 // State all dependencies and remove |second| so we don't generate an
131 // implicit dependency on the top level node.
132 std::deque<DependencyNode*>::iterator nodes_end(nodes.end());
133 result.append(" /* Dependencies */\n");
134 for (EdgeMap::const_iterator it = edges_.begin(); it != edges_.end(); ++it) {
135 result.append(" ");
136 result.append(get_node_name_callback_.Run(it->second));
137 result.append(" -> ");
138 result.append(get_node_name_callback_.Run(it->first));
139 result.append(";\n");
140
141 nodes_end = std::remove(nodes.begin(), nodes_end, it->second);
142 }
143 nodes.erase(nodes_end, nodes.end());
144
145 // Every node that doesn't depend on anything else will implicitly depend on
146 // the top level node.
147 result.append("\n /* Toplevel attachments */\n");
148 for (std::deque<DependencyNode*>::const_iterator it =
149 nodes.begin(); it != nodes.end(); ++it) {
150 result.append(" ");
151 result.append(get_node_name_callback_.Run(*it));
152 result.append(" -> ");
153 result.append(toplevel_name);
154 result.append(";\n");
155 }
156
157 result.append("\n /* Toplevel node */\n");
158 result.append(" ");
159 result.append(toplevel_name);
160 result.append(" [shape=box];\n");
161
162 result.append("}\n");
163 return result;
164 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698