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

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

Issue 6766004: Create a ProfileDependencyManager to order ProfileKeyedService destruction. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 9 years, 9 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 (c) 2011 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/profile_dependency_manager.h"
6
7 #include <algorithm>
8 #include <deque>
9
10 #include "chrome/browser/profiles/profile_keyed_service.h"
11 #include "chrome/browser/profiles/profile_keyed_service_factory.h"
12 #include "content/common/notification_service.h"
13
14 class Profile;
15
16 void ProfileDependencyManager::AddComponent(
17 ProfileKeyedServiceFactory* component) {
18 all_components_.push_back(component);
19 destruction_order_.clear();
20 }
21
22 void ProfileDependencyManager::RemoveComponent(
23 ProfileKeyedServiceFactory* component) {
24 all_components_.erase(std::remove(all_components_.begin(),
25 all_components_.end(),
26 component),
27 all_components_.end());
28
29 // Remove all dependency edges that contain this component.
30 EdgeMap::iterator it = edges_.begin();
31 while (it != edges_.end()) {
32 EdgeMap::iterator temp = it;
33 ++it;
34
35 if (temp->first == component || temp->second == component)
36 edges_.erase(temp);
37 }
38
39 destruction_order_.clear();
40 }
41
42 void ProfileDependencyManager::AddEdge(ProfileKeyedServiceFactory* depended,
43 ProfileKeyedServiceFactory* dependee) {
44 edges_.insert(std::make_pair(depended, dependee));
45 destruction_order_.clear();
46 }
47
48 // static
49 ProfileDependencyManager* ProfileDependencyManager::GetInstance() {
50 static ProfileDependencyManager* manager =
51 Singleton<ProfileDependencyManager>::get();
52 return manager;
53 }
54
55 ProfileDependencyManager::ProfileDependencyManager() {
56 // Listen for all Profile destruction messages so that we can rebroadcast
57 // them to all Factories in a safe order.
58 registrar_.Add(this,
59 NotificationType::PROFILE_DESTROYED,
60 NotificationService::AllSources());
61 }
62
63 ProfileDependencyManager::~ProfileDependencyManager() {}
64
65 void ProfileDependencyManager::BuildDestructionOrder() {
66 // Step 1: Build a set of nodes with no incoming edges.
67 std::deque<ProfileKeyedServiceFactory*> queue;
68 std::copy(all_components_.begin(),
69 all_components_.end(),
70 std::back_inserter(queue));
71
72 std::deque<ProfileKeyedServiceFactory*>::iterator queue_end = queue.end();
73 for (EdgeMap::const_iterator it = edges_.begin();
74 it != edges_.end(); ++it) {
75 queue_end = std::remove(queue.begin(), queue_end, it->second);
76 }
77 queue.erase(queue_end, queue.end());
78
79 // Step 2: Do the Kahn topological sort.
80 std::vector<ProfileKeyedServiceFactory*> output;
81 EdgeMap edges(edges_);
82 while (!queue.empty()) {
83 ProfileKeyedServiceFactory* node = queue.front();
84 queue.pop_front();
85 output.push_back(node);
86
87 std::pair<EdgeMap::iterator, EdgeMap::iterator> range =
88 edges.equal_range(node);
89 EdgeMap::iterator it = range.first;
90 while (it != range.second) {
91 ProfileKeyedServiceFactory* dest = it->second;
92 EdgeMap::iterator temp = it;
93 it++;
94 edges.erase(temp);
95
96 bool has_incoming_edges = false;
97 for (EdgeMap::iterator jt = edges.begin(); jt != edges.end(); ++jt) {
98 if (jt->second == dest) {
99 has_incoming_edges = true;
100 break;
101 }
102 }
103
104 if (!has_incoming_edges)
105 queue.push_back(dest);
106 }
107 }
108
109 if (edges.size()) {
110 NOTREACHED() << "Dependency graph has a cycle. We are doomed.";
111 }
112
113 std::reverse(output.begin(), output.end());
114 destruction_order_ = output;
115 }
116
117 void ProfileDependencyManager::Observe(NotificationType type,
118 const NotificationSource& source,
119 const NotificationDetails& details) {
Miranda Callahan 2011/03/29 19:07:04 Should probably make sure that the NotificationTyp
Elliot Glaysher 2011/03/29 22:18:29 No longer applicable.
120 Profile* profile = Source<Profile>(source).ptr();
121
122 if (destruction_order_.empty())
123 BuildDestructionOrder();
124
125 for (std::vector<ProfileKeyedServiceFactory*>::const_iterator it =
126 destruction_order_.begin(); it != destruction_order_.end(); ++it) {
Miranda Callahan 2011/03/29 19:07:04 nit: indent
Elliot Glaysher 2011/03/29 22:18:29 Indentation is correct? Breaking a statement is pr
127 (*it)->ProfileShutdown(profile);
128 }
129
130 for (std::vector<ProfileKeyedServiceFactory*>::const_iterator it =
131 destruction_order_.begin(); it != destruction_order_.end(); ++it) {
Miranda Callahan 2011/03/29 19:07:04 nit: indent
132 (*it)->ProfileDestroyed(profile);
133 }
134 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698