1c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be 3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file. 4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/at_exit.h" 6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/logging.h" 7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace base { 9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Keep a stack of registered AtExitManagers. We always operate on the most 11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// recent, and we should never have more than one outside of testing, when we 12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// use the shadow version of the constructor. We don't protect this for 13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// thread-safe access, since it will only be modified in testing. 14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic AtExitManager* g_top_manager = NULL; 15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottAtExitManager::AtExitManager() : next_manager_(NULL) { 17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(!g_top_manager); 18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott g_top_manager = this; 19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottAtExitManager::AtExitManager(bool shadow) : next_manager_(g_top_manager) { 22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(shadow || !g_top_manager); 23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott g_top_manager = this; 24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottAtExitManager::~AtExitManager() { 27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!g_top_manager) { 28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NOTREACHED() << "Tried to ~AtExitManager without an AtExitManager"; 29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(g_top_manager == this); 32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ProcessCallbacksNow(); 34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott g_top_manager = next_manager_; 35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// static 38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid AtExitManager::RegisterCallback(AtExitCallbackType func, void* param) { 39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!g_top_manager) { 40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NOTREACHED() << "Tried to RegisterCallback without an AtExitManager"; 41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(func); 45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott AutoLock lock(g_top_manager->lock_); 47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott g_top_manager->stack_.push(CallbackAndParam(func, param)); 48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// static 51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid AtExitManager::ProcessCallbacksNow() { 52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!g_top_manager) { 53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NOTREACHED() << "Tried to ProcessCallbacksNow without an AtExitManager"; 54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott AutoLock lock(g_top_manager->lock_); 58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott while (!g_top_manager->stack_.empty()) { 60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CallbackAndParam callback_and_param = g_top_manager->stack_.top(); 61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott g_top_manager->stack_.pop(); 62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott callback_and_param.func_(callback_and_param.param_); 64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} // namespace base 68