1c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be 3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file. 4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#ifndef BASE_AT_EXIT_H_ 6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define BASE_AT_EXIT_H_ 7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <stack> 9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/basictypes.h" 11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/lock.h" 12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace base { 14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// This class provides a facility similar to the CRT atexit(), except that 16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// we control when the callbacks are executed. Under Windows for a DLL they 17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// happen at a really bad time and under the loader lock. This facility is 18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// mostly used by base::Singleton. 19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// 20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// The usage is simple. Early in the main() or WinMain() scope create an 21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// AtExitManager object on the stack: 22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// int main(...) { 23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// base::AtExitManager exit_manager; 24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// 25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// } 26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// When the exit_manager object goes out of scope, all the registered 27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// callbacks and singleton destructors will be called. 28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass AtExitManager { 30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott protected: 31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // This constructor will allow this instance of AtExitManager to be created 32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // even if one already exists. This should only be used for testing! 33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // AtExitManagers are kept on a global stack, and it will be removed during 34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // destruction. This allows you to shadow another AtExitManager. 35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott explicit AtExitManager(bool shadow); 36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public: 38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott typedef void (*AtExitCallbackType)(void*); 39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott AtExitManager(); 41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // The dtor calls all the registered callbacks. Do not try to register more 43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // callbacks after this point. 44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ~AtExitManager(); 45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Registers the specified function to be called at exit. The prototype of 47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // the callback function is void func(). 48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott static void RegisterCallback(AtExitCallbackType func, void* param); 49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Calls the functions registered with RegisterCallback in LIFO order. It 51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // is possible to register new callbacks after calling this function. 52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott static void ProcessCallbacksNow(); 53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private: 55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott struct CallbackAndParam { 56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CallbackAndParam(AtExitCallbackType func, void* param) 57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott : func_(func), param_(param) { } 58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott AtExitCallbackType func_; 59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void* param_; 60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott }; 61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Lock lock_; 63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::stack<CallbackAndParam> stack_; 64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott AtExitManager* next_manager_; // Stack of managers to allow shadowing. 65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DISALLOW_COPY_AND_ASSIGN(AtExitManager); 67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(UNIT_TEST) 70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass ShadowingAtExitManager : public AtExitManager { 71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public: 72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ShadowingAtExitManager() : AtExitManager(true) {} 73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif // defined(UNIT_TEST) 75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} // namespace base 77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif // BASE_AT_EXIT_H_ 79