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