at_exit.h 2.32 KB
Newer Older
gejun's avatar
gejun committed
1 2 3 4 5 6 7 8 9
// 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_

#include <stack>

10 11 12
#include "butil/base_export.h"
#include "butil/basictypes.h"
#include "butil/synchronization/lock.h"
gejun's avatar
gejun committed
13

14
namespace butil {
gejun's avatar
gejun committed
15 16 17 18

// 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
19
// mostly used by butil::Singleton.
gejun's avatar
gejun committed
20 21 22 23
//
// The usage is simple. Early in the main() or WinMain() scope create an
// AtExitManager object on the stack:
// int main(...) {
24
//    butil::AtExitManager exit_manager;
gejun's avatar
gejun committed
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
//
// }
// When the exit_manager object goes out of scope, all the registered
// callbacks and singleton destructors will be called.

class BASE_EXPORT 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(void*).
  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:
56 57 58 59
  struct Callback {
    AtExitCallbackType func;
    void* param;
  };
60
  butil::Lock lock_;
61
  std::stack<Callback> stack_;
gejun's avatar
gejun committed
62 63 64 65 66 67 68 69 70 71 72 73
  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)

74
}  // namespace butil
gejun's avatar
gejun committed
75 76

#endif  // BASE_AT_EXIT_H_