[email protected] | 2edc286 | 2011-04-04 18:04:37 | [diff] [blame] | 1 | // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
[email protected] | b2e9729 | 2008-09-02 18:20:34 | [diff] [blame] | 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" | ||||
[email protected] | 2edc286 | 2011-04-04 18:04:37 | [diff] [blame] | 6 | |
7 | #include <stddef.h> | ||||
8 | #include <ostream> | ||||
9 | |||||
[email protected] | b2e9729 | 2008-09-02 18:20:34 | [diff] [blame] | 10 | #include "base/logging.h" |
11 | |||||
12 | namespace base { | ||||
13 | |||||
14 | // Keep a stack of registered AtExitManagers. We always operate on the most | ||||
[email protected] | 5ceb1b0 | 2011-04-22 22:09:35 | [diff] [blame] | 15 | // recent, and we should never have more than one outside of testing (for a |
16 | // statically linked version of this library). Testing may use the shadow | ||||
17 | // version of the constructor, and if we are building a dynamic library we may | ||||
18 | // end up with multiple AtExitManagers on the same process. We don't protect | ||||
19 | // this for thread-safe access, since it will only be modified in testing. | ||||
[email protected] | b2e9729 | 2008-09-02 18:20:34 | [diff] [blame] | 20 | static AtExitManager* g_top_manager = NULL; |
21 | |||||
[email protected] | 5ceb1b0 | 2011-04-22 22:09:35 | [diff] [blame] | 22 | AtExitManager::AtExitManager() : next_manager_(g_top_manager) { |
23 | // If multiple modules instantiate AtExitManagers they'll end up living in this | ||||
24 | // module... they have to coexist. | ||||
[email protected] | 63e39a28 | 2011-07-13 20:41:28 | [diff] [blame^] | 25 | #if !defined(COMPONENT_BUILD) |
[email protected] | b2e9729 | 2008-09-02 18:20:34 | [diff] [blame] | 26 | DCHECK(!g_top_manager); |
[email protected] | 5ceb1b0 | 2011-04-22 22:09:35 | [diff] [blame] | 27 | #endif |
[email protected] | b2e9729 | 2008-09-02 18:20:34 | [diff] [blame] | 28 | g_top_manager = this; |
29 | } | ||||
30 | |||||
[email protected] | b2e9729 | 2008-09-02 18:20:34 | [diff] [blame] | 31 | AtExitManager::~AtExitManager() { |
32 | if (!g_top_manager) { | ||||
33 | NOTREACHED() << "Tried to ~AtExitManager without an AtExitManager"; | ||||
34 | return; | ||||
35 | } | ||||
[email protected] | 5e0be64 | 2011-04-28 18:20:09 | [diff] [blame] | 36 | DCHECK_EQ(this, g_top_manager); |
[email protected] | b2e9729 | 2008-09-02 18:20:34 | [diff] [blame] | 37 | |
38 | ProcessCallbacksNow(); | ||||
39 | g_top_manager = next_manager_; | ||||
40 | } | ||||
41 | |||||
42 | // static | ||||
[email protected] | 9795ec1 | 2008-09-08 09:06:51 | [diff] [blame] | 43 | void AtExitManager::RegisterCallback(AtExitCallbackType func, void* param) { |
[email protected] | b2e9729 | 2008-09-02 18:20:34 | [diff] [blame] | 44 | if (!g_top_manager) { |
45 | NOTREACHED() << "Tried to RegisterCallback without an AtExitManager"; | ||||
46 | return; | ||||
47 | } | ||||
48 | |||||
[email protected] | 9795ec1 | 2008-09-08 09:06:51 | [diff] [blame] | 49 | DCHECK(func); |
50 | |||||
[email protected] | b2e9729 | 2008-09-02 18:20:34 | [diff] [blame] | 51 | AutoLock lock(g_top_manager->lock_); |
[email protected] | 9795ec1 | 2008-09-08 09:06:51 | [diff] [blame] | 52 | g_top_manager->stack_.push(CallbackAndParam(func, param)); |
[email protected] | b2e9729 | 2008-09-02 18:20:34 | [diff] [blame] | 53 | } |
54 | |||||
55 | // static | ||||
56 | void AtExitManager::ProcessCallbacksNow() { | ||||
57 | if (!g_top_manager) { | ||||
58 | NOTREACHED() << "Tried to ProcessCallbacksNow without an AtExitManager"; | ||||
59 | return; | ||||
60 | } | ||||
61 | |||||
62 | AutoLock lock(g_top_manager->lock_); | ||||
63 | |||||
64 | while (!g_top_manager->stack_.empty()) { | ||||
[email protected] | 9795ec1 | 2008-09-08 09:06:51 | [diff] [blame] | 65 | CallbackAndParam callback_and_param = g_top_manager->stack_.top(); |
[email protected] | b2e9729 | 2008-09-02 18:20:34 | [diff] [blame] | 66 | g_top_manager->stack_.pop(); |
[email protected] | 9795ec1 | 2008-09-08 09:06:51 | [diff] [blame] | 67 | |
68 | callback_and_param.func_(callback_and_param.param_); | ||||
[email protected] | b2e9729 | 2008-09-02 18:20:34 | [diff] [blame] | 69 | } |
70 | } | ||||
71 | |||||
[email protected] | eae9c06 | 2011-01-11 00:50:59 | [diff] [blame] | 72 | AtExitManager::AtExitManager(bool shadow) : next_manager_(g_top_manager) { |
73 | DCHECK(shadow || !g_top_manager); | ||||
74 | g_top_manager = this; | ||||
75 | } | ||||
76 | |||||
[email protected] | b2e9729 | 2008-09-02 18:20:34 | [diff] [blame] | 77 | } // namespace base |