Bug 1932613 - temporarily disable browser_ml_end_to_end.js for permanent failures...
[gecko.git] / xpcom / base / ClearOnShutdown.h
blobf927e3334a6f25ae397a3fc853bb6906cbce670f
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef mozilla_ClearOnShutdown_h
8 #define mozilla_ClearOnShutdown_h
10 #include "mozilla/LinkedList.h"
11 #include "mozilla/StaticPtr.h"
12 #include "mozilla/Array.h"
13 #include "ShutdownPhase.h"
14 #include "MainThreadUtils.h"
16 #include <functional>
19 * This header exports two public methods in the mozilla namespace:
21 * template<class SmartPtr>
22 * void ClearOnShutdown(SmartPtr *aPtr,
23 * aPhase=ShutdownPhase::XPCOMShutdownFinal)
25 * This function takes a pointer to a smart pointer and nulls the smart pointer
26 * on shutdown (and a particular phase of shutdown as needed). If a phase
27 * is specified, the ptr will be cleared at the start of that phase. Also,
28 * if a phase has already occurred when ClearOnShutdown() is called it will
29 * cause a MOZ_ASSERT. In case a phase is not explicitly cleared we will
30 * clear it on the next phase that occurs.
32 * This is useful if you have a global smart pointer object which you don't
33 * want to "leak" on shutdown.
35 * Although ClearOnShutdown will work with any smart pointer (i.e., nsCOMPtr,
36 * RefPtr, StaticRefPtr, and StaticAutoPtr), you probably want to
37 * use it only with StaticRefPtr and StaticAutoPtr. There is no way to undo a
38 * call to ClearOnShutdown, so you can call it only on smart pointers which you
39 * know will live until the program shuts down. In practice, these are likely
40 * global variables, which should be Static{Ref,Auto}Ptr.
42 * template <typename CallableT>
43 * void RunOnShutdown(CallableT&& aCallable,
44 * aPhase = ShutdownPhase::XPCOMShutdownFinal)
46 * This function takes a callable and executes it upon shutdown at the start of
47 * the specified phase. If the phase has already occurred when RunOnShutdown()
48 * is called, it will cause a MOZ_ASSERT. In case a phase is not explicitly
49 * cleared, we will clear it on the next phase that occurs.
51 * ClearOnShutdown and RunOnShutdown are both currently main-thread only because
52 * we don't want to accidentally free an object from a different thread than the
53 * one it was created on.
56 namespace mozilla {
58 namespace ClearOnShutdown_Internal {
60 class ShutdownObserver : public LinkedListElement<ShutdownObserver> {
61 public:
62 virtual void Shutdown() = 0;
63 virtual ~ShutdownObserver() = default;
66 template <class SmartPtr>
67 class PointerClearer : public ShutdownObserver {
68 public:
69 explicit PointerClearer(SmartPtr* aPtr) : mPtr(aPtr) {}
71 virtual void Shutdown() override {
72 if (mPtr) {
73 *mPtr = nullptr;
77 private:
78 SmartPtr* mPtr;
81 class FunctionInvoker : public ShutdownObserver {
82 public:
83 template <typename CallableT>
84 explicit FunctionInvoker(CallableT&& aCallable)
85 : mCallable(std::forward<CallableT>(aCallable)) {}
87 virtual void Shutdown() override {
88 if (!mCallable) {
89 return;
92 mCallable();
95 private:
96 std::function<void()> mCallable;
99 void InsertIntoShutdownList(ShutdownObserver* aShutdownObserver,
100 ShutdownPhase aPhase);
102 typedef LinkedList<ShutdownObserver> ShutdownList;
103 extern Array<StaticAutoPtr<ShutdownList>,
104 static_cast<size_t>(ShutdownPhase::ShutdownPhase_Length)>
105 sShutdownObservers;
106 extern ShutdownPhase sCurrentClearOnShutdownPhase;
108 } // namespace ClearOnShutdown_Internal
110 template <class SmartPtr>
111 inline void ClearOnShutdown(
112 SmartPtr* aPtr, ShutdownPhase aPhase = ShutdownPhase::XPCOMShutdownFinal) {
113 using namespace ClearOnShutdown_Internal;
115 MOZ_ASSERT(NS_IsMainThread());
116 MOZ_ASSERT(aPhase != ShutdownPhase::ShutdownPhase_Length);
118 InsertIntoShutdownList(new PointerClearer<SmartPtr>(aPtr), aPhase);
121 template <typename CallableT>
122 inline void RunOnShutdown(
123 CallableT&& aCallable,
124 ShutdownPhase aPhase = ShutdownPhase::XPCOMShutdownFinal) {
125 using namespace ClearOnShutdown_Internal;
127 MOZ_ASSERT(NS_IsMainThread());
128 MOZ_ASSERT(aPhase != ShutdownPhase::ShutdownPhase_Length);
130 InsertIntoShutdownList(
131 new FunctionInvoker(std::forward<CallableT>(aCallable)), aPhase);
134 inline bool PastShutdownPhase(ShutdownPhase aPhase) {
135 MOZ_ASSERT(NS_IsMainThread());
137 return size_t(ClearOnShutdown_Internal::sCurrentClearOnShutdownPhase) >=
138 size_t(aPhase);
141 // Called by AdvanceShutdownPhase each time we switch a phase. Will null out
142 // pointers added by ClearOnShutdown for all phases up to and including aPhase.
143 void KillClearOnShutdown(ShutdownPhase aPhase);
145 } // namespace mozilla
147 #endif