• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "base/at_exit.h"
6 
7 #include <stddef.h>
8 #include <ostream>
9 
10 #include "base/logging.h"
11 
12 namespace base {
13 
14 // Keep a stack of registered AtExitManagers.  We always operate on the most
15 // recent, and we should never have more than one outside of testing, when we
16 // use the shadow version of the constructor.  We don't protect this for
17 // thread-safe access, since it will only be modified in testing.
18 static AtExitManager* g_top_manager = NULL;
19 
AtExitManager()20 AtExitManager::AtExitManager() : next_manager_(NULL) {
21   DCHECK(!g_top_manager);
22   g_top_manager = this;
23 }
24 
~AtExitManager()25 AtExitManager::~AtExitManager() {
26   if (!g_top_manager) {
27     NOTREACHED() << "Tried to ~AtExitManager without an AtExitManager";
28     return;
29   }
30   DCHECK(g_top_manager == this);
31 
32   ProcessCallbacksNow();
33   g_top_manager = next_manager_;
34 }
35 
36 // static
RegisterCallback(AtExitCallbackType func,void * param)37 void AtExitManager::RegisterCallback(AtExitCallbackType func, void* param) {
38   if (!g_top_manager) {
39     NOTREACHED() << "Tried to RegisterCallback without an AtExitManager";
40     return;
41   }
42 
43   DCHECK(func);
44 
45   AutoLock lock(g_top_manager->lock_);
46   g_top_manager->stack_.push(CallbackAndParam(func, param));
47 }
48 
49 // static
ProcessCallbacksNow()50 void AtExitManager::ProcessCallbacksNow() {
51   if (!g_top_manager) {
52     NOTREACHED() << "Tried to ProcessCallbacksNow without an AtExitManager";
53     return;
54   }
55 
56   AutoLock lock(g_top_manager->lock_);
57 
58   while (!g_top_manager->stack_.empty()) {
59     CallbackAndParam callback_and_param = g_top_manager->stack_.top();
60     g_top_manager->stack_.pop();
61 
62     callback_and_param.func_(callback_and_param.param_);
63   }
64 }
65 
AtExitManager(bool shadow)66 AtExitManager::AtExitManager(bool shadow) : next_manager_(g_top_manager) {
67   DCHECK(shadow || !g_top_manager);
68   g_top_manager = this;
69 }
70 
71 }  // namespace base
72