13f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen// Copyright (c) 2011 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_ 73345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#pragma once 8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <stack> 10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 11ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/base_api.h" 12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/basictypes.h" 1372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "base/synchronization/lock.h" 14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace base { 16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// This class provides a facility similar to the CRT atexit(), except that 18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// we control when the callbacks are executed. Under Windows for a DLL they 19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// happen at a really bad time and under the loader lock. This facility is 20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// mostly used by base::Singleton. 21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// 22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// The usage is simple. Early in the main() or WinMain() scope create an 23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// AtExitManager object on the stack: 24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// int main(...) { 25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// base::AtExitManager exit_manager; 26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// 27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// } 28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// When the exit_manager object goes out of scope, all the registered 29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// callbacks and singleton destructors will be called. 30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 31ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenclass BASE_API AtExitManager { 32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public: 33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott typedef void (*AtExitCallbackType)(void*); 34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott AtExitManager(); 36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // The dtor calls all the registered callbacks. Do not try to register more 38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // callbacks after this point. 39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ~AtExitManager(); 40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Registers the specified function to be called at exit. The prototype of 42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // the callback function is void func(). 43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott static void RegisterCallback(AtExitCallbackType func, void* param); 44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Calls the functions registered with RegisterCallback in LIFO order. It 46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // is possible to register new callbacks after calling this function. 47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott static void ProcessCallbacksNow(); 48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 493f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen protected: 503f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // This constructor will allow this instance of AtExitManager to be created 513f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // even if one already exists. This should only be used for testing! 523f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // AtExitManagers are kept on a global stack, and it will be removed during 533f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // destruction. This allows you to shadow another AtExitManager. 543f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen explicit AtExitManager(bool shadow); 553f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private: 57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott struct CallbackAndParam { 58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CallbackAndParam(AtExitCallbackType func, void* param) 59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott : func_(func), param_(param) { } 60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott AtExitCallbackType func_; 61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void* param_; 62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott }; 63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 6472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen base::Lock lock_; 65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::stack<CallbackAndParam> stack_; 66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott AtExitManager* next_manager_; // Stack of managers to allow shadowing. 67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DISALLOW_COPY_AND_ASSIGN(AtExitManager); 69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(UNIT_TEST) 72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass ShadowingAtExitManager : public AtExitManager { 73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public: 74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ShadowingAtExitManager() : AtExitManager(true) {} 75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif // defined(UNIT_TEST) 77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} // namespace base 79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif // BASE_AT_EXIT_H_ 81