0

Add a void* parameter to the AtExitManager callbacks.

Review URL: http://codereview.chromium.org/1805

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@1835 0039d316-1c4b-4281-b951-d872f2087c98
This commit is contained in:
deanm@google.com
2008-09-08 09:06:51 +00:00
parent 88eb0a862e
commit 9795ec11c9
4 changed files with 47 additions and 30 deletions

@ -35,14 +35,16 @@ AtExitManager::~AtExitManager() {
}
// static
void AtExitManager::RegisterCallback(AtExitCallbackType func) {
void AtExitManager::RegisterCallback(AtExitCallbackType func, void* param) {
if (!g_top_manager) {
NOTREACHED() << "Tried to RegisterCallback without an AtExitManager";
return;
}
DCHECK(func);
AutoLock lock(g_top_manager->lock_);
g_top_manager->stack_.push(func);
g_top_manager->stack_.push(CallbackAndParam(func, param));
}
// static
@ -55,12 +57,11 @@ void AtExitManager::ProcessCallbacksNow() {
AutoLock lock(g_top_manager->lock_);
while (!g_top_manager->stack_.empty()) {
AtExitCallbackType func = g_top_manager->stack_.top();
CallbackAndParam callback_and_param = g_top_manager->stack_.top();
g_top_manager->stack_.pop();
if (func)
func();
callback_and_param.func_(callback_and_param.param_);
}
}
} // namespace base

@ -35,7 +35,7 @@ class AtExitManager {
AtExitManager(bool shadow);
public:
typedef void (*AtExitCallbackType)();
typedef void (*AtExitCallbackType)(void*);
AtExitManager();
@ -45,15 +45,22 @@ class AtExitManager {
// Registers the specified function to be called at exit. The prototype of
// the callback function is void func().
static void RegisterCallback(AtExitCallbackType func);
static void RegisterCallback(AtExitCallbackType func, void* param);
// Calls the functions registered with RegisterCallback in LIFO order. It
// is possible to register new callbacks after calling this function.
static void ProcessCallbacksNow();
private:
struct CallbackAndParam {
CallbackAndParam(AtExitCallbackType func, void* param)
: func_(func), param_(param) { }
AtExitCallbackType func_;
void* param_;
};
Lock lock_;
std::stack<AtExitCallbackType> stack_;
std::stack<CallbackAndParam> stack_;
AtExitManager* next_manager_; // Stack of managers to allow shadowing.
DISALLOW_COPY_AND_ASSIGN(AtExitManager);
@ -62,4 +69,3 @@ class AtExitManager {
} // namespace base
#endif // BASE_AT_EXIT_H_

@ -18,11 +18,11 @@ class ShadowingAtExitManager : public base::AtExitManager {
int g_test_counter_1 = 0;
int g_test_counter_2 = 0;
void IncrementTestCounter1() {
void IncrementTestCounter1(void* unused) {
++g_test_counter_1;
}
void IncrementTestCounter2() {
void IncrementTestCounter2(void* unused) {
++g_test_counter_2;
}
@ -31,19 +31,27 @@ void ZeroTestCounters() {
g_test_counter_2 = 0;
}
void ExpectCounter1IsZero() {
void ExpectCounter1IsZero(void* unused) {
EXPECT_EQ(0, g_test_counter_1);
}
void ExpectParamIsNull(void* param) {
EXPECT_EQ(static_cast<void*>(NULL), param);
}
void ExpectParamIsCounter(void* param) {
EXPECT_EQ(&g_test_counter_1, param);
}
} // namespace
TEST(AtExitTest, Basic) {
ShadowingAtExitManager shadowing_at_exit_manager;
ZeroTestCounters();
base::AtExitManager::RegisterCallback(&IncrementTestCounter1);
base::AtExitManager::RegisterCallback(&IncrementTestCounter2);
base::AtExitManager::RegisterCallback(&IncrementTestCounter1);
base::AtExitManager::RegisterCallback(&IncrementTestCounter1, NULL);
base::AtExitManager::RegisterCallback(&IncrementTestCounter2, NULL);
base::AtExitManager::RegisterCallback(&IncrementTestCounter1, NULL);
EXPECT_EQ(0, g_test_counter_1);
EXPECT_EQ(0, g_test_counter_2);
@ -56,9 +64,9 @@ TEST(AtExitTest, LIFOOrder) {
ShadowingAtExitManager shadowing_at_exit_manager;
ZeroTestCounters();
base::AtExitManager::RegisterCallback(&IncrementTestCounter1);
base::AtExitManager::RegisterCallback(&ExpectCounter1IsZero);
base::AtExitManager::RegisterCallback(&IncrementTestCounter2);
base::AtExitManager::RegisterCallback(&IncrementTestCounter1, NULL);
base::AtExitManager::RegisterCallback(&ExpectCounter1IsZero, NULL);
base::AtExitManager::RegisterCallback(&IncrementTestCounter2, NULL);
EXPECT_EQ(0, g_test_counter_1);
EXPECT_EQ(0, g_test_counter_2);
@ -67,3 +75,11 @@ TEST(AtExitTest, LIFOOrder) {
EXPECT_EQ(1, g_test_counter_2);
}
TEST(AtExitTest, Param) {
ShadowingAtExitManager shadowing_at_exit_manager;
base::AtExitManager::RegisterCallback(&ExpectParamIsNull, NULL);
base::AtExitManager::RegisterCallback(&ExpectParamIsCounter,
&g_test_counter_1);
base::AtExitManager::ProcessCallbacksNow();
}

@ -2,12 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_SINGLETON_H__
#define BASE_SINGLETON_H__
#include <stdlib.h>
#include <utility>
#ifndef BASE_SINGLETON_H_
#define BASE_SINGLETON_H_
#include "base/at_exit.h"
#include "base/atomicops.h"
@ -125,7 +121,7 @@ class Singleton {
&instance_, reinterpret_cast<base::subtle::AtomicWord>(newval));
if (Traits::kRegisterAtExit)
base::AtExitManager::RegisterCallback(OnExit);
base::AtExitManager::RegisterCallback(OnExit, NULL);
return newval;
}
@ -159,7 +155,7 @@ class Singleton {
private:
// Adapter function for use with AtExit(). This should be called single
// threaded, but we might as well take the precautions anyway.
static void OnExit() {
static void OnExit(void* unused) {
// AtExit should only ever be register after the singleton instance was
// created. We should only ever get here with a valid instance_ pointer.
Traits::Delete(reinterpret_cast<Type*>(
@ -172,6 +168,4 @@ template <typename Type, typename Traits, typename DifferentiatingType>
base::subtle::AtomicWord Singleton<Type, Traits, DifferentiatingType>::
instance_ = 0;
#endif // BASE_SINGLETON_H__
#endif // BASE_SINGLETON_H_