summaryrefslogtreecommitdiffstats
path: root/base/at_exit.cc
diff options
context:
space:
mode:
authordeanm@google.com <deanm@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-08-11 14:02:06 +0000
committerdeanm@google.com <deanm@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-08-11 14:02:06 +0000
commit4ac8f670af190931c88542ae57295da97e2971ce (patch)
treec53779e5876223856392e291d340c20088ab339e /base/at_exit.cc
parent663fe3c5c9327b3b604fe7f2c7fd3f4d5cccc4e4 (diff)
downloadchromium_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.cc79
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