diff options
author | deanm@google.com <deanm@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-08-11 14:02:06 +0000 |
---|---|---|
committer | deanm@google.com <deanm@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-08-11 14:02:06 +0000 |
commit | 4ac8f670af190931c88542ae57295da97e2971ce (patch) | |
tree | c53779e5876223856392e291d340c20088ab339e /base/at_exit.cc | |
parent | 663fe3c5c9327b3b604fe7f2c7fd3f4d5cccc4e4 (diff) | |
download | chromium_src-4ac8f670af190931c88542ae57295da97e2971ce.zip chromium_src-4ac8f670af190931c88542ae57295da97e2971ce.tar.gz chromium_src-4ac8f670af190931c88542ae57295da97e2971ce.tar.bz2 |
Allow multiple AtExitManagers to be chained in a stack, this allows much easier testing for code that is expecting to be run via an AtExitManager. This actually cleaned up a lot of the at exit code.
Clean up singleton_dll_unittest. It is no longer windows specific DLL, and now is much simpler, and builds and runs cross platform.
BUG=1314043
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@646 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base/at_exit.cc')
-rw-r--r-- | base/at_exit.cc | 79 |
1 files changed, 42 insertions, 37 deletions
diff --git a/base/at_exit.cc b/base/at_exit.cc index 1f56057..734de74 100644 --- a/base/at_exit.cc +++ b/base/at_exit.cc @@ -30,58 +30,63 @@ #include "base/at_exit.h" #include "base/logging.h" -namespace { - -std::stack<base::AtExitCallbackType>* g_atexit_queue = NULL; -Lock* g_atexit_lock = NULL; - -void ProcessCallbacks() { - if (!g_atexit_queue) - return; - base::AtExitCallbackType func = NULL; - while(!g_atexit_queue->empty()) { - func = g_atexit_queue->top(); - g_atexit_queue->pop(); - if (func) - func(); - } -} - -} // namespace +// Keep a stack of registered AtExitManagers. We always operate on the most +// recent, and we should never have more than one outside of testing, when we +// use the shadow version of the constructor. We don't protect this for +// thread-safe access, since it will only be modified in testing. +static std::stack<base::AtExitManager*> g_managers; namespace base { AtExitManager::AtExitManager() { - DCHECK(NULL == g_atexit_queue); - DCHECK(NULL == g_atexit_lock); - g_atexit_lock = &lock_; - g_atexit_queue = &atexit_queue_; + DCHECK(g_managers.empty()); + g_managers.push(this); +} + +AtExitManager::AtExitManager(bool shadow) { + DCHECK(shadow || g_managers.empty()); + g_managers.push(this); } AtExitManager::~AtExitManager() { - AutoLock lock(lock_); - ProcessCallbacks(); - g_atexit_queue = NULL; - g_atexit_lock = NULL; + if (g_managers.empty()) { + NOTREACHED() << "Tried to ~AtExitManager without a AtExitManager"; + return; + } + DCHECK(g_managers.top() == this); + + ProcessCallbacksNow(); + g_managers.pop(); } +// static void AtExitManager::RegisterCallback(AtExitCallbackType func) { - DCHECK(NULL != g_atexit_queue); - DCHECK(NULL != g_atexit_lock); - if (!g_atexit_lock) + if (g_managers.empty()) { + NOTREACHED() << "Tried to RegisterCallback without a AtExitManager"; return; - AutoLock lock(*g_atexit_lock); - if (g_atexit_queue) - g_atexit_queue->push(func); + } + + AtExitManager* manager = g_managers.top(); + AutoLock lock(manager->lock_); + manager->stack_.push(func); } +// static void AtExitManager::ProcessCallbacksNow() { - DCHECK(NULL != g_atexit_lock); - if (!g_atexit_lock) + if (g_managers.empty()) { + NOTREACHED() << "Tried to RegisterCallback without a AtExitManager"; return; - AutoLock lock(*g_atexit_lock); - DCHECK(NULL != g_atexit_queue); - ProcessCallbacks(); + } + + AtExitManager* manager = g_managers.top(); + AutoLock lock(manager->lock_); + + while (!manager->stack_.empty()) { + base::AtExitCallbackType func = manager->stack_.top(); + manager->stack_.pop(); + if (func) + func(); + } } } // namespace base |