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
diff --git a/base/SConscript b/base/SConscript
index 719e29b..b8d9da9 100644
--- a/base/SConscript
+++ b/base/SConscript
@@ -200,23 +200,6 @@
       ],
   )
 
-
-env_tests_dll = env_tests.Clone()
-env_tests_dll.Append(
-    CPPDEFINES = [
-        '_WINDLL',
-        'SINGLETON_UNITTEST_EXPORTS',
-    ],
-)
-dll = env_tests_dll.ChromeSharedLibrary(['singleton_dll_unittest.dll',
-                                   'singleton_dll_unittest.lib',
-                                   'singleton_dll_unittest.ilk',
-                                   'singleton_dll_unittest.pdb'],
-                                  ['singleton_dll_unittest.cc',
-                                   'build/singleton_dll_unittest.def'])
-i = env.Install('$TARGET_ROOT', dll[0])
-env.Alias('base', i)
-
 env_tests.ChromeTestProgram(['debug_message.exe',
                    'debug_message.ilk',
                    'debug_message.pdb'],
@@ -269,8 +252,6 @@
     'win_util_unittest.cc',
     'word_iterator_unittest.cc',
     'wmi_util_unittest.cc',
-
-    dll[1],
 ]
 
 if env['PLATFORM'] == 'win32':
diff --git a/base/at_exit.cc b/base/at_exit.cc
index 1f560578..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
diff --git a/base/at_exit.h b/base/at_exit.h
index 8b9f946..123935da 100644
--- a/base/at_exit.h
+++ b/base/at_exit.h
@@ -54,6 +54,12 @@
 // callbacks and singleton destructors will be called.
 
 class AtExitManager {
+ protected:
+  // This constructor will allow this instance of AtExitManager to be created
+  // even if on already exists.  This should only be used for testing!
+  // AtExitManagers are kept on a global stack, and it will be removed during
+  // destruction.  This allows you to shadow another AtExitManager.
+  AtExitManager(bool shadow);
  public:
   AtExitManager();
 
@@ -71,7 +77,7 @@
 
  private:
   Lock lock_;
-  std::stack<base::AtExitCallbackType> atexit_queue_;
+  std::stack<base::AtExitCallbackType> stack_;
   DISALLOW_EVIL_CONSTRUCTORS(AtExitManager);
 };
 
diff --git a/base/base.sln b/base/base.sln
index c9280643..94a02d3 100644
--- a/base/base.sln
+++ b/base/base.sln
@@ -36,12 +36,6 @@
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlib", "..\third_party\zlib\zlib.vcproj", "{8423AF0D-4B88-4EBF-94E1-E4D00D00E21C}"
 EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "singleton_dll_unittest", "build\singleton_unittest.vcproj", "{E457F2FB-4708-4001-9B1C-275D7BD7F2A8}"
-	ProjectSection(ProjectDependencies) = postProject
-		{1832A374-8A74-4F9E-B536-69A699B3E165} = {1832A374-8A74-4F9E-B536-69A699B3E165}
-		{8C27D792-2648-4F5E-9ED0-374276327308} = {8C27D792-2648-4F5E-9ED0-374276327308}
-	EndProjectSection
-EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gtest", "..\testing\gtest.vcproj", "{BFE8E2A7-3B3B-43B0-A994-3058B852DB8B}"
 EndProject
 Global
diff --git a/base/build/singleton_dll_unittest.def b/base/build/singleton_dll_unittest.def
deleted file mode 100644
index 6ad4d90..0000000
--- a/base/build/singleton_dll_unittest.def
+++ /dev/null
@@ -1,9 +0,0 @@
-EXPORTS
-	SingletonInt1
-	SingletonInt2
-	SingletonInt3
-	SingletonInt4
-	SingletonInt5
-	SingletonNoLeak
-	SingletonLeak
-	GetLeakySingleton
diff --git a/base/build/singleton_dll_unittest.vsprops b/base/build/singleton_dll_unittest.vsprops
deleted file mode 100644
index a3eb79bb..0000000
--- a/base/build/singleton_dll_unittest.vsprops
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="Windows-1252"?>
-<VisualStudioPropertySheet
-	ProjectType="Visual C++"
-	Version="8.00"
-	Name="singleton_dll_unittest"
-	>
-	<Tool
-		Name="VCCLCompilerTool"
-		PreprocessorDefinitions="SINGLETON_UNITTEST_EXPORTS"
-	/>
-	<Tool
-		Name="VCLinkerTool"
-		ModuleDefinitionFile="singleton_dll_unittest.def"
-	/>
-</VisualStudioPropertySheet>
diff --git a/base/build/singleton_unittest.vcproj b/base/build/singleton_unittest.vcproj
deleted file mode 100644
index 6fcb715..0000000
--- a/base/build/singleton_unittest.vcproj
+++ /dev/null
@@ -1,157 +0,0 @@
-<?xml version="1.0" encoding="Windows-1252"?>
-<VisualStudioProject
-	ProjectType="Visual C++"
-	Version="8.00"
-	Name="singleton_dll_unittest"
-	ProjectGUID="{E457F2FB-4708-4001-9B1C-275D7BD7F2A8}"
-	RootNamespace="singleton_unittest"
-	Keyword="Win32Proj"
-	>
-	<Platforms>
-		<Platform
-			Name="Win32"
-		/>
-	</Platforms>
-	<ToolFiles>
-	</ToolFiles>
-	<Configurations>
-		<Configuration
-			Name="Debug|Win32"
-			ConfigurationType="2"
-			InheritedPropertySheets="$(SolutionDir)..\build\debug.vsprops;.\singleton_dll_unittest.vsprops"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLinkerTool"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCManifestTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCAppVerifierTool"
-			/>
-			<Tool
-				Name="VCWebDeploymentTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-		</Configuration>
-		<Configuration
-			Name="Release|Win32"
-			ConfigurationType="2"
-			InheritedPropertySheets="$(SolutionDir)..\build\release.vsprops;.\singleton_dll_unittest.vsprops"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLinkerTool"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCManifestTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCAppVerifierTool"
-			/>
-			<Tool
-				Name="VCWebDeploymentTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-		</Configuration>
-	</Configurations>
-	<References>
-	</References>
-	<Files>
-		<File
-			RelativePath="..\singleton_dll_unittest.cc"
-			>
-		</File>
-		<File
-			RelativePath=".\singleton_dll_unittest.def"
-			>
-		</File>
-		<File
-			RelativePath="..\singleton_dll_unittest.h"
-			>
-		</File>
-	</Files>
-	<Globals>
-	</Globals>
-</VisualStudioProject>
diff --git a/base/singleton_dll_unittest.cc b/base/singleton_dll_unittest.cc
deleted file mode 100644
index 6892965..0000000
--- a/base/singleton_dll_unittest.cc
+++ /dev/null
@@ -1,118 +0,0 @@
-// Copyright 2008, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//    * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//    * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//    * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "base/singleton_dll_unittest.h"
-#include "base/at_exit.h"
-#include "base/logging.h"
-
-namespace {
-
-base::AtExitManager g_exit_manager;
-
-}   // namespace
-
-BOOL APIENTRY DllMain(HMODULE module, DWORD reason_for_call, LPVOID reserved) {
-  switch (reason_for_call) {
-    case DLL_PROCESS_ATTACH:
-      DisableThreadLibraryCalls(module);
-      break;
-    case DLL_THREAD_ATTACH:
-    case DLL_THREAD_DETACH:
-      break;
-    case DLL_PROCESS_DETACH:
-      break;
-  }
-  return TRUE;
-}
-
-COMPILE_ASSERT(DefaultSingletonTraits<int>::kRegisterAtExit == true, a);
-
-template<typename Type>
-struct LockTrait : public DefaultSingletonTraits<Type> {
-};
-
-struct Init5Trait : public DefaultSingletonTraits<int> {
-  static int* New() {
-    return new int(5);
-  }
-};
-
-struct CallbackTrait : public CustomAllocTrait<CallBackFunc> {
-  static void Delete(CallBackFunc* p) {
-    if (*p)
-      (*p)();
-    CHECK(CustomAllocTrait<CallBackFunc>::Delete(p));
-  }
-};
-
-struct NoLeakTrait : public CallbackTrait {
-};
-
-struct LeakTrait : public CallbackTrait {
-  static const bool kRegisterAtExit = false;
-};
-
-SINGLETON_UNITTEST_API int* WINAPI SingletonInt1() {
-  return Singleton<int>::get();
-}
-
-SINGLETON_UNITTEST_API int* WINAPI SingletonInt2() {
-  // Force to use a different singleton than SingletonInt1.
-  return Singleton<int, DefaultSingletonTraits<int> >::get();
-}
-
-class DummyDifferentiatingClass {
-};
-
-SINGLETON_UNITTEST_API int* WINAPI SingletonInt3() {
-  // Force to use a different singleton than SingletonInt1 and SingletonInt2.
-  // Note that any type can be used; int, float, std::wstring...
-  return Singleton<int, DefaultSingletonTraits<int>,
-                   DummyDifferentiatingClass>::get();
-}
-
-SINGLETON_UNITTEST_API int* WINAPI SingletonInt4() {
-  return Singleton<int, LockTrait<int> >::get();
-}
-
-SINGLETON_UNITTEST_API int* WINAPI SingletonInt5() {
-  return Singleton<int, Init5Trait>::get();
-}
-
-SINGLETON_UNITTEST_API void WINAPI SingletonNoLeak(CallBackFunc CallOnQuit) {
-  *Singleton<CallBackFunc, NoLeakTrait>::get() = CallOnQuit;
-}
-
-SINGLETON_UNITTEST_API void WINAPI SingletonLeak(CallBackFunc CallOnQuit) {
-  *Singleton<CallBackFunc, LeakTrait>::get() = CallOnQuit;
-}
-
-SINGLETON_UNITTEST_API CallBackFunc* WINAPI GetLeakySingleton() {
-  return Singleton<CallBackFunc, LeakTrait>::get();
-}
diff --git a/base/singleton_dll_unittest.h b/base/singleton_dll_unittest.h
deleted file mode 100644
index d16172205..0000000
--- a/base/singleton_dll_unittest.h
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright 2008, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//    * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//    * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//    * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#ifndef BASE_SINGLETON_DLL_UNITTEST_H__
-#define BASE_SINGLETON_DLL_UNITTEST_H__
-
-#include "base/singleton.h"
-
-#ifdef SINGLETON_UNITTEST_EXPORTS
-#define SINGLETON_UNITTEST_API __declspec(dllexport)
-#else
-#define SINGLETON_UNITTEST_API __declspec(dllimport)
-#endif
-
-// Function pointer for singleton getters.
-typedef int* (WINAPI* SingletonIntFunc)();
-
-// Callback function to be called on library unload.
-typedef void (WINAPI* CallBackFunc)();
-
-// Leaky/nonleak singleton initialization.
-typedef void (WINAPI* LeakySingletonFunc)(CallBackFunc);
-
-// Retrieve the leaky singleton for later disposal.
-typedef CallBackFunc* (WINAPI* GetLeakySingletonFunc)();
-
-// When using new/delete, the heap is destroyed on library unload. So use
-// VirtualAlloc/VirtualFree to bypass this behavior.
-template<typename Type>
-struct CustomAllocTrait : public DefaultSingletonTraits<Type> {
-  static Type* New() {
-    return static_cast<Type*>(VirtualAlloc(NULL, sizeof(Type), MEM_COMMIT,
-                                           PAGE_READWRITE));
-  }
-
-  static bool Delete(Type* p) {
-    return 0!=VirtualFree(p, 0, MEM_RELEASE);
-  }
-};
-
-// 1 and 2 share the same instance.
-// 3 simply use a different key.
-// 4 sets kMustCallNewExactlyOnce to true.
-// 5 default initialize to 5.
-extern "C" SINGLETON_UNITTEST_API int* WINAPI SingletonInt1();
-extern "C" SINGLETON_UNITTEST_API int* WINAPI SingletonInt2();
-extern "C" SINGLETON_UNITTEST_API int* WINAPI SingletonInt3();
-extern "C" SINGLETON_UNITTEST_API int* WINAPI SingletonInt4();
-extern "C" SINGLETON_UNITTEST_API int* WINAPI SingletonInt5();
-
-extern "C" SINGLETON_UNITTEST_API void WINAPI SingletonNoLeak(
-    CallBackFunc CallOnQuit);
-extern "C" SINGLETON_UNITTEST_API void WINAPI SingletonLeak(
-    CallBackFunc CallOnQuit);
-extern "C" SINGLETON_UNITTEST_API CallBackFunc* WINAPI GetLeakySingleton();
-
-#endif  // BASE_SINGLETON_DLL_UNITTEST_H__
diff --git a/base/singleton_unittest.cc b/base/singleton_unittest.cc
index 5d21593..167fa78c 100644
--- a/base/singleton_unittest.cc
+++ b/base/singleton_unittest.cc
@@ -27,54 +27,99 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-#include "testing/gtest/include/gtest/gtest.h"
-#include "base/singleton_dll_unittest.h"
+#include "base/at_exit.h"
 #include "base/file_util.h"
 #include "base/path_service.h"
+#include "base/singleton.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+class ShadowingAtExitManager : public base::AtExitManager {
+ public:
+  ShadowingAtExitManager() : AtExitManager(true) { }
+};
+
+COMPILE_ASSERT(DefaultSingletonTraits<int>::kRegisterAtExit == true, a);
+
+template<typename Type>
+struct LockTrait : public DefaultSingletonTraits<Type> {
+};
+
+struct Init5Trait : public DefaultSingletonTraits<int> {
+  static int* New() {
+    return new int(5);
+  }
+};
+
+typedef void (*CallbackFunc)();
+
+struct CallbackTrait : public DefaultSingletonTraits<CallbackFunc> {
+  static void Delete(CallbackFunc* p) {
+    if (*p)
+      (*p)();
+    DefaultSingletonTraits<CallbackFunc>::Delete(p);
+  }
+};
+
+struct NoLeakTrait : public CallbackTrait {
+};
+
+struct LeakTrait : public CallbackTrait {
+  static const bool kRegisterAtExit = false;
+};
+
+int* SingletonInt1() {
+  return Singleton<int>::get();
+}
+
+int* SingletonInt2() {
+  // Force to use a different singleton than SingletonInt1.
+  return Singleton<int, DefaultSingletonTraits<int> >::get();
+}
+
+class DummyDifferentiatingClass {
+};
+
+int* SingletonInt3() {
+  // Force to use a different singleton than SingletonInt1 and SingletonInt2.
+  // Note that any type can be used; int, float, std::wstring...
+  return Singleton<int, DefaultSingletonTraits<int>,
+                   DummyDifferentiatingClass>::get();
+}
+
+int* SingletonInt4() {
+  return Singleton<int, LockTrait<int> >::get();
+}
+
+int* SingletonInt5() {
+  return Singleton<int, Init5Trait>::get();
+}
+
+void SingletonNoLeak(CallbackFunc CallOnQuit) {
+  *Singleton<CallbackFunc, NoLeakTrait>::get() = CallOnQuit;
+}
+
+void SingletonLeak(CallbackFunc CallOnQuit) {
+  *Singleton<CallbackFunc, LeakTrait>::get() = CallOnQuit;
+}
+
+CallbackFunc* GetLeakySingleton() {
+  return Singleton<CallbackFunc, LeakTrait>::get();
+}
+
+}  // namespace
 
 class SingletonTest : public testing::Test {
  public:
-  SingletonTest() {
-  }
+  SingletonTest() { }
 
   virtual void SetUp() {
-    module_ = NULL;
     non_leak_called_ = false;
     leaky_called_ = false;
   }
 
-  virtual void TearDown() {
-    ASSERT_FALSE(module_);
-  }
-
-  static bool IsTestCaseDisabled() {
-    // Check if the dll exists beside the executable.
-    std::wstring path;
-    PathService::Get(base::DIR_EXE, &path);
-    file_util::AppendToPath(&path, kLibrary);
-    return !file_util::PathExists(path);
-  }
-
  protected:
-  void LoadLibrary() {
-    ASSERT_FALSE(module_);
-    module_ = ::LoadLibrary(kLibrary);
-    ASSERT_TRUE(module_ != NULL);
-  }
-
-  void FreeLibrary() {
-    ASSERT_TRUE(module_ != NULL);
-    ASSERT_TRUE(::FreeLibrary(module_));
-    module_ = NULL;
-  }
-
-  template<typename T>
-  void GetProc(const char* function_name, T* function) {
-    ASSERT_TRUE(module_ != NULL);
-    *function = reinterpret_cast<T>(GetProcAddress(module_, function_name));
-    ASSERT_TRUE(*function);
-  }
-
   void VerifiesCallbacks() {
     EXPECT_TRUE(non_leak_called_);
     EXPECT_FALSE(leaky_called_);
@@ -89,17 +134,15 @@
     leaky_called_ = false;
   }
 
-  static void WINAPI CallbackNoLeak() {
+  static void CallbackNoLeak() {
     non_leak_called_ = true;
   }
 
-  static void WINAPI CallbackLeak() {
+  static void CallbackLeak() {
     leaky_called_ = true;
   }
 
  private:
-  static const wchar_t* const kLibrary;
-  HMODULE module_;
   static bool non_leak_called_;
   static bool leaky_called_;
 };
@@ -107,48 +150,35 @@
 bool SingletonTest::non_leak_called_ = false;
 bool SingletonTest::leaky_called_ = false;
 
-const wchar_t* const SingletonTest::kLibrary = L"singleton_dll_unittest.dll";
-
 TEST_F(SingletonTest, Basic) {
-  if (IsTestCaseDisabled())
-    return;
-
   int* singleton_int_1;
   int* singleton_int_2;
   int* singleton_int_3;
   int* singleton_int_4;
   int* singleton_int_5;
-  CallBackFunc* leaky_singleton;
+  CallbackFunc* leaky_singleton;
 
-  LoadLibrary();
   {
-    SingletonIntFunc sut1;
-    SingletonIntFunc sut2;
-    SingletonIntFunc sut3;
-    SingletonIntFunc sut4;
-    SingletonIntFunc sut5;
+    ShadowingAtExitManager sem;
     {
-      GetProc("SingletonInt1", &sut1);
-      singleton_int_1 = sut1();
+      singleton_int_1 = SingletonInt1();
     }
     // Ensure POD type initialization.
     EXPECT_EQ(*singleton_int_1, 0);
     *singleton_int_1 = 1;
 
-    EXPECT_EQ(singleton_int_1, sut1());
+    EXPECT_EQ(singleton_int_1, SingletonInt1());
     EXPECT_EQ(*singleton_int_1, 1);
 
     {
-      GetProc("SingletonInt2", &sut2);
-      singleton_int_2 = sut2();
+      singleton_int_2 = SingletonInt2();
     }
     // Same instance that 1.
     EXPECT_EQ(*singleton_int_2, 1);
     EXPECT_EQ(singleton_int_1, singleton_int_2);
 
     {
-      GetProc("SingletonInt3", &sut3);
-      singleton_int_3 = sut3();
+      singleton_int_3 = SingletonInt3();
     }
     // Different instance than 1 and 2.
     EXPECT_EQ(*singleton_int_3, 0);
@@ -158,8 +188,7 @@
     EXPECT_EQ(*singleton_int_2, 1);
 
     {
-      GetProc("SingletonInt4", &sut4);
-      singleton_int_4 = sut4();
+      singleton_int_4 = SingletonInt4();
     }
     // Use a lock for creation. Not really tested at length.
     EXPECT_EQ(*singleton_int_4, 0);
@@ -168,60 +197,38 @@
     EXPECT_NE(singleton_int_3, singleton_int_4);
 
     {
-      GetProc("SingletonInt5", &sut5);
-      singleton_int_5 = sut5();
+      singleton_int_5 = SingletonInt5();
     }
     // Is default initialized to 5.
     EXPECT_EQ(*singleton_int_5, 5);
     EXPECT_NE(singleton_int_1, singleton_int_5);
     EXPECT_NE(singleton_int_3, singleton_int_5);
     EXPECT_NE(singleton_int_4, singleton_int_5);
-#ifdef _DEBUG
-    // In release, the optimizer may make both exports use exactly the same
-    // code.
-    EXPECT_NE(sut1, sut2);
-#endif
-    EXPECT_NE(sut2, sut3);
-    EXPECT_NE(sut3, sut4);
-    EXPECT_NE(sut4, sut5);
 
-    LeakySingletonFunc noleak;
-    GetProc("SingletonNoLeak", &noleak);
-    noleak(&CallbackNoLeak);
-    LeakySingletonFunc leak;
-    GetProc("SingletonLeak", &leak);
-    leak(&CallbackLeak);
-    GetLeakySingletonFunc get_leaky;
-    GetProc("GetLeakySingleton", &get_leaky);
-    leaky_singleton = get_leaky();
+    SingletonNoLeak(&CallbackNoLeak);
+    SingletonLeak(&CallbackLeak);
+    leaky_singleton = GetLeakySingleton();
     EXPECT_TRUE(leaky_singleton);
   }
-  FreeLibrary();
 
   // Verify that only the expected callback has been called.
   VerifiesCallbacks();
   // Delete the leaky singleton. It is interesting to note that Purify does
   // *not* detect the leak when this call is commented out. :(
-  EXPECT_TRUE(CustomAllocTrait<CallBackFunc>::Delete(leaky_singleton));
+  DefaultSingletonTraits<CallbackFunc>::Delete(leaky_singleton);
 
-  LoadLibrary();
   {
+    ShadowingAtExitManager sem;
     // Verifiy that the variables were reset.
     {
-      SingletonIntFunc sut1;
-      GetProc("SingletonInt1", &sut1);
-      singleton_int_1 = sut1();
+      singleton_int_1 = SingletonInt1();
       EXPECT_EQ(*singleton_int_1, 0);
     }
     {
-      SingletonIntFunc sut5;
-      GetProc("SingletonInt5", &sut5);
-      singleton_int_5 = sut5();
+      singleton_int_5 = SingletonInt5();
       EXPECT_EQ(*singleton_int_5, 5);
     }
   }
   // The leaky singleton shouldn't leak since SingletonLeak has not been called.
-  FreeLibrary();
-
   VerifiesCallbacksNotCalled();
 }