Chromium Code Reviews| OLD | NEW |
|---|---|
| (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 } | |
| OLD | NEW |