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