/work/obj-fuzz/dist/include/mozilla/ArenaRefPtr.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 | | |
8 | | /* smart pointer for strong references to nsPresArena-allocated objects |
9 | | that might be held onto until the arena's destruction */ |
10 | | |
11 | | #include "mozilla/Assertions.h" |
12 | | #include "mozilla/RefPtr.h" |
13 | | |
14 | | #ifndef mozilla_ArenaRefPtr_h |
15 | | #define mozilla_ArenaRefPtr_h |
16 | | |
17 | | class nsPresArena; |
18 | | |
19 | | namespace mozilla { |
20 | | |
21 | | /** |
22 | | * A class for holding strong references to nsPresArena-allocated |
23 | | * objects. |
24 | | * |
25 | | * Since the arena's lifetime is not related to the refcounts |
26 | | * of the objects allocated within it, it is possible to have a strong |
27 | | * reference to an arena-allocated object that lives until the |
28 | | * destruction of the arena. An ArenaRefPtr acts like a weak reference |
29 | | * in that it will clear its referent if the arena is about to go away. |
30 | | * |
31 | | * T must be a class that has these two methods: |
32 | | * |
33 | | * static mozilla::ArenaObjectID ArenaObjectID(); |
34 | | * U* Arena(); |
35 | | * |
36 | | * where U is a class that has these two methods: |
37 | | * |
38 | | * void RegisterArenaRefPtr(ArenaRefPtr<T>*); |
39 | | * void DeregisterArenaRefPtr(ArenaRefPtr<T>*); |
40 | | * |
41 | | * Currently, both nsPresArena and nsIPresShell can be used as U. |
42 | | * |
43 | | * The ArenaObjectID method must return the mozilla::ArenaObjectID that |
44 | | * uniquely identifies T, and the Arena method must return the nsPresArena |
45 | | * (or a proxy for it) in which the object was allocated. |
46 | | */ |
47 | | template<typename T> |
48 | | class ArenaRefPtr |
49 | | { |
50 | | friend class ::nsPresArena; |
51 | | |
52 | | public: |
53 | | ArenaRefPtr() |
54 | 0 | { |
55 | 0 | AssertValidType(); |
56 | 0 | } |
57 | | |
58 | | template<typename I> |
59 | | MOZ_IMPLICIT ArenaRefPtr(already_AddRefed<I>& aRhs) |
60 | | { |
61 | | AssertValidType(); |
62 | | assign(aRhs); |
63 | | } |
64 | | |
65 | | template<typename I> |
66 | | MOZ_IMPLICIT ArenaRefPtr(already_AddRefed<I>&& aRhs) |
67 | | { |
68 | | AssertValidType(); |
69 | | assign(aRhs); |
70 | | } |
71 | | |
72 | | MOZ_IMPLICIT ArenaRefPtr(T* aRhs) |
73 | | { |
74 | | AssertValidType(); |
75 | | assign(aRhs); |
76 | | } |
77 | | |
78 | | template<typename I> |
79 | | ArenaRefPtr<T>& operator=(already_AddRefed<I>& aRhs) |
80 | | { |
81 | | assign(aRhs); |
82 | | return *this; |
83 | | } |
84 | | |
85 | | template<typename I> |
86 | | ArenaRefPtr<T>& operator=(already_AddRefed<I>&& aRhs) |
87 | | { |
88 | | assign(aRhs); |
89 | | return *this; |
90 | | } |
91 | | |
92 | | ArenaRefPtr<T>& operator=(T* aRhs) |
93 | 0 | { |
94 | 0 | assign(aRhs); |
95 | 0 | return *this; |
96 | 0 | } |
97 | | |
98 | 0 | ~ArenaRefPtr() { assign(nullptr); } |
99 | | |
100 | 0 | operator T*() const & { return get(); } |
101 | | operator T*() const && = delete; |
102 | 0 | explicit operator bool() const { return !!mPtr; } |
103 | 0 | bool operator!() const { return !mPtr; } |
104 | 0 | T* operator->() const { return mPtr.operator->(); } |
105 | 0 | T& operator*() const { return *get(); } |
106 | | |
107 | 0 | T* get() const { return mPtr; } |
108 | | |
109 | | private: |
110 | | void AssertValidType(); |
111 | | |
112 | | /** |
113 | | * Clears the pointer to the arena-allocated object but skips the usual |
114 | | * step of deregistering the ArenaRefPtr from the nsPresArena. This |
115 | | * method is called by nsPresArena when clearing all registered ArenaRefPtrs |
116 | | * so that it can deregister them all at once, avoiding hash table churn. |
117 | | */ |
118 | | void ClearWithoutDeregistering() |
119 | 0 | { |
120 | 0 | mPtr = nullptr; |
121 | 0 | } |
122 | | |
123 | | template<typename I> |
124 | | void assign(already_AddRefed<I>& aSmartPtr) |
125 | | { |
126 | | RefPtr<T> newPtr(aSmartPtr); |
127 | | assignFrom(newPtr); |
128 | | } |
129 | | |
130 | | template<typename I> |
131 | | void assign(already_AddRefed<I>&& aSmartPtr) |
132 | | { |
133 | | RefPtr<T> newPtr(aSmartPtr); |
134 | | assignFrom(newPtr); |
135 | | } |
136 | | |
137 | 0 | void assign(T* aPtr) { assignFrom(aPtr); } |
138 | | |
139 | | template<typename I> |
140 | | void assignFrom(I& aPtr) |
141 | 0 | { |
142 | 0 | if (aPtr == mPtr) { |
143 | 0 | return; |
144 | 0 | } |
145 | 0 | bool sameArena = mPtr && aPtr && mPtr->Arena() == aPtr->Arena(); |
146 | 0 | if (mPtr && !sameArena) { |
147 | 0 | MOZ_ASSERT(mPtr->Arena()); |
148 | 0 | mPtr->Arena()->DeregisterArenaRefPtr(this); |
149 | 0 | } |
150 | 0 | mPtr = std::move(aPtr); |
151 | 0 | if (mPtr && !sameArena) { |
152 | 0 | MOZ_ASSERT(mPtr->Arena()); |
153 | 0 | mPtr->Arena()->RegisterArenaRefPtr(this); |
154 | 0 | } |
155 | 0 | } |
156 | | |
157 | | RefPtr<T> mPtr; |
158 | | }; |
159 | | |
160 | | } // namespace mozilla |
161 | | |
162 | | #endif // mozilla_ArenaRefPtr_h |