// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef BASE_AT_EXIT_H_ #define BASE_AT_EXIT_H_ #pragma once #include #include "base/base_api.h" #include "base/basictypes.h" #include "base/synchronization/lock.h" namespace base { // This class provides a facility similar to the CRT atexit(), except that // we control when the callbacks are executed. Under Windows for a DLL they // happen at a really bad time and under the loader lock. This facility is // mostly used by base::Singleton. // // The usage is simple. Early in the main() or WinMain() scope create an // AtExitManager object on the stack: // int main(...) { // base::AtExitManager exit_manager; // // } // When the exit_manager object goes out of scope, all the registered // callbacks and singleton destructors will be called. class BASE_API AtExitManager { public: typedef void (*AtExitCallbackType)(void*); AtExitManager(); // The dtor calls all the registered callbacks. Do not try to register more // callbacks after this point. ~AtExitManager(); // Registers the specified function to be called at exit. The prototype of // the callback function is void 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(); protected: // This constructor will allow this instance of AtExitManager to be created // even if one 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. explicit AtExitManager(bool shadow); private: struct CallbackAndParam { CallbackAndParam(AtExitCallbackType func, void* param) : func_(func), param_(param) { } AtExitCallbackType func_; void* param_; }; base::Lock lock_; std::stack stack_; AtExitManager* next_manager_; // Stack of managers to allow shadowing. DISALLOW_COPY_AND_ASSIGN(AtExitManager); }; #if defined(UNIT_TEST) class ShadowingAtExitManager : public AtExitManager { public: ShadowingAtExitManager() : AtExitManager(true) {} }; #endif // defined(UNIT_TEST) } // namespace base #endif // BASE_AT_EXIT_H_