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:
@ -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_
|
||||
|
Reference in New Issue
Block a user