// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "chrome/browser/profiles/profile_dependency_manager.h" #include <algorithm> #include <deque> #include <iterator> #include "chrome/browser/profiles/profile_keyed_service.h" #include "chrome/browser/profiles/profile_keyed_service_factory.h" #include "content/common/notification_service.h" class Profile; void ProfileDependencyManager::AddComponent( ProfileKeyedServiceFactory* component) { all_components_.push_back(component); destruction_order_.clear(); } void ProfileDependencyManager::RemoveComponent( ProfileKeyedServiceFactory* component) { all_components_.erase(std::remove(all_components_.begin(), all_components_.end(), component), all_components_.end()); // Remove all dependency edges that contain this component. EdgeMap::iterator it = edges_.begin(); while (it != edges_.end()) { EdgeMap::iterator temp = it; ++it; if (temp->first == component || temp->second == component) edges_.erase(temp); } destruction_order_.clear(); } void ProfileDependencyManager::AddEdge(ProfileKeyedServiceFactory* depended, ProfileKeyedServiceFactory* dependee) { edges_.insert(std::make_pair(depended, dependee)); destruction_order_.clear(); } void ProfileDependencyManager::DestroyProfileServices(Profile* profile) { if (destruction_order_.empty()) BuildDestructionOrder(); for (std::vector<ProfileKeyedServiceFactory*>::const_iterator it = destruction_order_.begin(); it != destruction_order_.end(); ++it) { (*it)->ProfileShutdown(profile); } for (std::vector<ProfileKeyedServiceFactory*>::const_iterator it = destruction_order_.begin(); it != destruction_order_.end(); ++it) { (*it)->ProfileDestroyed(profile); } } // static ProfileDependencyManager* ProfileDependencyManager::GetInstance() { return Singleton<ProfileDependencyManager>::get(); } ProfileDependencyManager::ProfileDependencyManager() {} ProfileDependencyManager::~ProfileDependencyManager() {} void ProfileDependencyManager::BuildDestructionOrder() { // Step 1: Build a set of nodes with no incoming edges. std::deque<ProfileKeyedServiceFactory*> queue; std::copy(all_components_.begin(), all_components_.end(), std::back_inserter(queue)); std::deque<ProfileKeyedServiceFactory*>::iterator queue_end = queue.end(); for (EdgeMap::const_iterator it = edges_.begin(); it != edges_.end(); ++it) { queue_end = std::remove(queue.begin(), queue_end, it->second); } queue.erase(queue_end, queue.end()); // Step 2: Do the Kahn topological sort. std::vector<ProfileKeyedServiceFactory*> output; EdgeMap edges(edges_); while (!queue.empty()) { ProfileKeyedServiceFactory* node = queue.front(); queue.pop_front(); output.push_back(node); std::pair<EdgeMap::iterator, EdgeMap::iterator> range = edges.equal_range(node); EdgeMap::iterator it = range.first; while (it != range.second) { ProfileKeyedServiceFactory* dest = it->second; EdgeMap::iterator temp = it; it++; edges.erase(temp); bool has_incoming_edges = false; for (EdgeMap::iterator jt = edges.begin(); jt != edges.end(); ++jt) { if (jt->second == dest) { has_incoming_edges = true; break; } } if (!has_incoming_edges) queue.push_back(dest); } } if (edges.size()) { NOTREACHED() << "Dependency graph has a cycle. We are doomed."; } std::reverse(output.begin(), output.end()); destruction_order_ = output; }