/src/mozilla-central/xpcom/base/ClearOnShutdown.h
Line | Count | Source (jump to first uncovered line) |
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/. */ |
6 | | |
7 | | #ifndef mozilla_ClearOnShutdown_h |
8 | | #define mozilla_ClearOnShutdown_h |
9 | | |
10 | | #include "mozilla/LinkedList.h" |
11 | | #include "mozilla/StaticPtr.h" |
12 | | #include "mozilla/Array.h" |
13 | | #include "MainThreadUtils.h" |
14 | | |
15 | | /* |
16 | | * This header exports one public method in the mozilla namespace: |
17 | | * |
18 | | * template<class SmartPtr> |
19 | | * void ClearOnShutdown(SmartPtr *aPtr, aPhase=ShutdownPhase::ShutdownFinal) |
20 | | * |
21 | | * This function takes a pointer to a smart pointer and nulls the smart pointer |
22 | | * on shutdown (and a particular phase of shutdown as needed). If a phase |
23 | | * is specified, the ptr will be cleared at the start of that phase. Also, |
24 | | * if a phase has already occurred when ClearOnShutdown() is called it will |
25 | | * cause a MOZ_ASSERT. In case a phase is not explicitly cleared we will |
26 | | * clear it on the next phase that occurs. |
27 | | * |
28 | | * This is useful if you have a global smart pointer object which you don't |
29 | | * want to "leak" on shutdown. |
30 | | * |
31 | | * Although ClearOnShutdown will work with any smart pointer (i.e., nsCOMPtr, |
32 | | * nsRefPtr, nsAutoPtr, StaticRefPtr, and StaticAutoPtr), you probably want to |
33 | | * use it only with StaticRefPtr and StaticAutoPtr. There is no way to undo a |
34 | | * call to ClearOnShutdown, so you can call it only on smart pointers which you |
35 | | * know will live until the program shuts down. In practice, these are likely |
36 | | * global variables, which should be Static{Ref,Auto}Ptr. |
37 | | * |
38 | | * ClearOnShutdown is currently main-thread only because we don't want to |
39 | | * accidentally free an object from a different thread than the one it was |
40 | | * created on. |
41 | | */ |
42 | | |
43 | | namespace mozilla { |
44 | | |
45 | | // Must be contiguous starting at 0 |
46 | | enum class ShutdownPhase { |
47 | | NotInShutdown = 0, |
48 | | WillShutdown, |
49 | | Shutdown, |
50 | | ShutdownThreads, |
51 | | ShutdownLoaders, |
52 | | ShutdownFinal, |
53 | | ShutdownPhase_Length, // never pass this value |
54 | | First = WillShutdown, // for iteration |
55 | | Last = ShutdownFinal |
56 | | }; |
57 | | |
58 | | namespace ClearOnShutdown_Internal { |
59 | | |
60 | | class ShutdownObserver : public LinkedListElement<ShutdownObserver> |
61 | | { |
62 | | public: |
63 | | virtual void Shutdown() = 0; |
64 | | virtual ~ShutdownObserver() |
65 | | { |
66 | | } |
67 | | }; |
68 | | |
69 | | template<class SmartPtr> |
70 | | class PointerClearer : public ShutdownObserver |
71 | | { |
72 | | public: |
73 | | explicit PointerClearer(SmartPtr* aPtr) |
74 | | : mPtr(aPtr) |
75 | 0 | { |
76 | 0 | } Unexecuted instantiation: mozilla::ClearOnShutdown_Internal::PointerClearer<mozilla::StaticAutoPtr<mozilla::plugins::FunctionHookArray> >::PointerClearer(mozilla::StaticAutoPtr<mozilla::plugins::FunctionHookArray>*) Unexecuted instantiation: mozilla::ClearOnShutdown_Internal::PointerClearer<mozilla::StaticAutoPtr<mozilla::dom::ContentChild::ShutdownCanary> >::PointerClearer(mozilla::StaticAutoPtr<mozilla::dom::ContentChild::ShutdownCanary>*) |
77 | | |
78 | | virtual void Shutdown() override |
79 | 0 | { |
80 | 0 | if (mPtr) { |
81 | 0 | *mPtr = nullptr; |
82 | 0 | } |
83 | 0 | } Unexecuted instantiation: mozilla::ClearOnShutdown_Internal::PointerClearer<mozilla::StaticAutoPtr<mozilla::plugins::FunctionHookArray> >::Shutdown() Unexecuted instantiation: mozilla::ClearOnShutdown_Internal::PointerClearer<mozilla::StaticAutoPtr<mozilla::dom::ContentChild::ShutdownCanary> >::Shutdown() |
84 | | |
85 | | private: |
86 | | SmartPtr* mPtr; |
87 | | }; |
88 | | |
89 | | typedef LinkedList<ShutdownObserver> ShutdownList; |
90 | | extern Array<StaticAutoPtr<ShutdownList>, |
91 | | static_cast<size_t>(ShutdownPhase::ShutdownPhase_Length)> sShutdownObservers; |
92 | | extern ShutdownPhase sCurrentShutdownPhase; |
93 | | |
94 | | } // namespace ClearOnShutdown_Internal |
95 | | |
96 | | template<class SmartPtr> |
97 | | inline void |
98 | | ClearOnShutdown(SmartPtr* aPtr, ShutdownPhase aPhase = ShutdownPhase::ShutdownFinal) |
99 | 0 | { |
100 | 0 | using namespace ClearOnShutdown_Internal; |
101 | 0 |
|
102 | 0 | MOZ_ASSERT(NS_IsMainThread()); |
103 | 0 | MOZ_ASSERT(aPhase != ShutdownPhase::ShutdownPhase_Length); |
104 | 0 |
|
105 | 0 | // Adding a ClearOnShutdown for a "past" phase is an error. |
106 | 0 | if (!(static_cast<size_t>(sCurrentShutdownPhase) < static_cast<size_t>(aPhase))) { |
107 | 0 | MOZ_ASSERT(false, "ClearOnShutdown for phase that already was cleared"); |
108 | 0 | *aPtr = nullptr; |
109 | 0 | return; |
110 | 0 | } |
111 | 0 |
|
112 | 0 | if (!(sShutdownObservers[static_cast<size_t>(aPhase)])) { |
113 | 0 | sShutdownObservers[static_cast<size_t>(aPhase)] = new ShutdownList(); |
114 | 0 | } |
115 | 0 | sShutdownObservers[static_cast<size_t>(aPhase)]->insertBack(new PointerClearer<SmartPtr>(aPtr)); |
116 | 0 | } Unexecuted instantiation: void mozilla::ClearOnShutdown<mozilla::StaticAutoPtr<mozilla::plugins::FunctionHookArray> >(mozilla::StaticAutoPtr<mozilla::plugins::FunctionHookArray>*, mozilla::ShutdownPhase) Unexecuted instantiation: void mozilla::ClearOnShutdown<mozilla::StaticAutoPtr<mozilla::dom::ContentChild::ShutdownCanary> >(mozilla::StaticAutoPtr<mozilla::dom::ContentChild::ShutdownCanary>*, mozilla::ShutdownPhase) |
117 | | |
118 | | // Called when XPCOM is shutting down, after all shutdown notifications have |
119 | | // been sent and after all threads' event loops have been purged. |
120 | | void KillClearOnShutdown(ShutdownPhase aPhase); |
121 | | |
122 | | } // namespace mozilla |
123 | | |
124 | | #endif |