Line data Source code
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 : /* A class for non-null strong pointers to reference-counted objects. */
8 :
9 : #ifndef mozilla_OwningNonNull_h
10 : #define mozilla_OwningNonNull_h
11 :
12 : #include "nsAutoPtr.h"
13 : #include "nsCycleCollectionNoteChild.h"
14 :
15 : namespace mozilla {
16 :
17 : template<class T>
18 68 : class OwningNonNull
19 : {
20 : public:
21 75 : OwningNonNull() {}
22 :
23 2 : MOZ_IMPLICIT OwningNonNull(T& aValue)
24 2 : {
25 2 : init(&aValue);
26 2 : }
27 :
28 : template<class U>
29 0 : MOZ_IMPLICIT OwningNonNull(already_AddRefed<U>&& aValue)
30 0 : {
31 0 : init(aValue);
32 0 : }
33 :
34 : template<class U>
35 0 : MOZ_IMPLICIT OwningNonNull(const OwningNonNull<U>& aValue)
36 0 : {
37 0 : init(aValue);
38 0 : }
39 :
40 : // This is no worse than get() in terms of const handling.
41 19 : operator T&() const
42 : {
43 19 : MOZ_ASSERT(mInited);
44 19 : MOZ_ASSERT(mPtr, "OwningNonNull<T> was set to null");
45 19 : return *mPtr;
46 : }
47 :
48 57 : operator T*() const
49 : {
50 57 : MOZ_ASSERT(mInited);
51 57 : MOZ_ASSERT(mPtr, "OwningNonNull<T> was set to null");
52 57 : return mPtr;
53 : }
54 :
55 : // Conversion to bool is always true, so delete to catch errors
56 : explicit operator bool() const = delete;
57 :
58 : T*
59 21 : operator->() const
60 : {
61 21 : MOZ_ASSERT(mInited);
62 21 : MOZ_ASSERT(mPtr, "OwningNonNull<T> was set to null");
63 21 : return mPtr;
64 : }
65 :
66 : OwningNonNull<T>&
67 75 : operator=(T* aValue)
68 : {
69 75 : init(aValue);
70 75 : return *this;
71 : }
72 :
73 : OwningNonNull<T>&
74 0 : operator=(T& aValue)
75 : {
76 0 : init(&aValue);
77 0 : return *this;
78 : }
79 :
80 : template<class U>
81 : OwningNonNull<T>&
82 0 : operator=(already_AddRefed<U>&& aValue)
83 : {
84 0 : init(aValue);
85 0 : return *this;
86 : }
87 :
88 : template<class U>
89 : OwningNonNull<T>&
90 : operator=(const OwningNonNull<U>& aValue)
91 : {
92 : init(aValue);
93 : return *this;
94 : }
95 :
96 : // Don't allow assigning nullptr, it makes no sense
97 : void operator=(decltype(nullptr)) = delete;
98 :
99 0 : already_AddRefed<T> forget()
100 : {
101 : #ifdef DEBUG
102 0 : mInited = false;
103 : #endif
104 0 : return mPtr.forget();
105 : }
106 :
107 : template<class U>
108 : void
109 : forget(U** aOther)
110 : {
111 : #ifdef DEBUG
112 : mInited = false;
113 : #endif
114 : mPtr.forget(aOther);
115 : }
116 :
117 : // Make us work with smart pointer helpers that expect a get().
118 0 : T* get() const
119 : {
120 0 : MOZ_ASSERT(mInited);
121 0 : MOZ_ASSERT(mPtr);
122 0 : return mPtr;
123 : }
124 :
125 : template<typename U>
126 : void swap(U& aOther)
127 : {
128 : mPtr.swap(aOther);
129 : #ifdef DEBUG
130 : mInited = mPtr;
131 : #endif
132 : }
133 :
134 : // We have some consumers who want to check whether we're inited in non-debug
135 : // builds as well. Luckily, we have the invariant that we're inited precisely
136 : // when mPtr is non-null.
137 19 : bool isInitialized() const
138 : {
139 19 : MOZ_ASSERT(!!mPtr == mInited, "mInited out of sync with mPtr?");
140 19 : return mPtr;
141 : }
142 :
143 : protected:
144 : template<typename U>
145 77 : void init(U&& aValue)
146 : {
147 77 : mPtr = aValue;
148 77 : MOZ_ASSERT(mPtr);
149 : #ifdef DEBUG
150 77 : mInited = true;
151 : #endif
152 77 : }
153 :
154 : RefPtr<T> mPtr;
155 : #ifdef DEBUG
156 : bool mInited = false;
157 : #endif
158 : };
159 :
160 : template <typename T>
161 : inline void
162 0 : ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
163 : OwningNonNull<T>& aField,
164 : const char* aName,
165 : uint32_t aFlags = 0)
166 : {
167 0 : CycleCollectionNoteChild(aCallback, aField.get(), aName, aFlags);
168 0 : }
169 :
170 : } // namespace mozilla
171 :
172 : // Declared in nsCOMPtr.h
173 : template<class T> template<class U>
174 0 : nsCOMPtr<T>::nsCOMPtr(const mozilla::OwningNonNull<U>& aOther)
175 0 : : nsCOMPtr(aOther.get())
176 0 : {}
177 :
178 : template<class T> template<class U>
179 : nsCOMPtr<T>&
180 0 : nsCOMPtr<T>::operator=(const mozilla::OwningNonNull<U>& aOther)
181 : {
182 0 : return operator=(aOther.get());
183 : }
184 :
185 : // Declared in mozilla/RefPtr.h
186 : template<class T> template<class U>
187 0 : RefPtr<T>::RefPtr(const mozilla::OwningNonNull<U>& aOther)
188 0 : : RefPtr(aOther.get())
189 0 : {}
190 :
191 : template<class T> template<class U>
192 : RefPtr<T>&
193 0 : RefPtr<T>::operator=(const mozilla::OwningNonNull<U>& aOther)
194 : {
195 0 : return operator=(aOther.get());
196 : }
197 :
198 : #endif // mozilla_OwningNonNull_h
|