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"
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.
58 namespace ClearOnShutdown_Internal
{
60 class ShutdownObserver
: public LinkedListElement
<ShutdownObserver
> {
62 virtual void Shutdown() = 0;
63 virtual ~ShutdownObserver() = default;
66 template <class SmartPtr
>
67 class PointerClearer
: public ShutdownObserver
{
69 explicit PointerClearer(SmartPtr
* aPtr
) : mPtr(aPtr
) {}
71 virtual void Shutdown() override
{
81 class FunctionInvoker
: public ShutdownObserver
{
83 template <typename CallableT
>
84 explicit FunctionInvoker(CallableT
&& aCallable
)
85 : mCallable(std::forward
<CallableT
>(aCallable
)) {}
87 virtual void Shutdown() override
{
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
)>
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
) >=
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