1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3  * License, v. 2.0. If a copy of the MPL was not distributed with this
4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 
6 #ifndef nsHtml5StreamParserPtr_h
7 #define nsHtml5StreamParserPtr_h
8 
9 #include "nsHtml5StreamParser.h"
10 #include "nsHtml5StreamParserReleaser.h"
11 #include "nsThreadUtils.h"
12 #include "mozilla/dom/DocGroup.h"
13 
14 /**
15  * Like nsRefPtr except release is proxied to the main
16  * thread. Mostly copied from nsRefPtr.
17  */
18 class nsHtml5StreamParserPtr {
19  private:
assign_with_AddRef(nsHtml5StreamParser * rawPtr)20   void assign_with_AddRef(nsHtml5StreamParser* rawPtr) {
21     if (rawPtr) rawPtr->AddRef();
22     assign_assuming_AddRef(rawPtr);
23   }
begin_assignment()24   void** begin_assignment() {
25     assign_assuming_AddRef(0);
26     return reinterpret_cast<void**>(&mRawPtr);
27   }
assign_assuming_AddRef(nsHtml5StreamParser * newPtr)28   void assign_assuming_AddRef(nsHtml5StreamParser* newPtr) {
29     nsHtml5StreamParser* oldPtr = mRawPtr;
30     mRawPtr = newPtr;
31     if (oldPtr) release(oldPtr);
32   }
release(nsHtml5StreamParser * aPtr)33   void release(nsHtml5StreamParser* aPtr) {
34     nsCOMPtr<nsIRunnable> releaser = new nsHtml5StreamParserReleaser(aPtr);
35     if (NS_FAILED(aPtr->DispatchToMain(releaser.forget()))) {
36       NS_WARNING("Failed to dispatch releaser event.");
37     }
38   }
39 
40  private:
41   nsHtml5StreamParser* mRawPtr;
42 
43  public:
~nsHtml5StreamParserPtr()44   ~nsHtml5StreamParserPtr() {
45     if (mRawPtr) release(mRawPtr);
46   }
47   // Constructors
nsHtml5StreamParserPtr()48   nsHtml5StreamParserPtr()
49       : mRawPtr(0)
50   // default constructor
51   {}
nsHtml5StreamParserPtr(const nsHtml5StreamParserPtr & aSmartPtr)52   nsHtml5StreamParserPtr(const nsHtml5StreamParserPtr& aSmartPtr)
53       : mRawPtr(aSmartPtr.mRawPtr)
54   // copy-constructor
55   {
56     if (mRawPtr) mRawPtr->AddRef();
57   }
nsHtml5StreamParserPtr(nsHtml5StreamParser * aRawPtr)58   explicit nsHtml5StreamParserPtr(nsHtml5StreamParser* aRawPtr)
59       : mRawPtr(aRawPtr)
60   // construct from a raw pointer (of the right type)
61   {
62     if (mRawPtr) mRawPtr->AddRef();
63   }
64   // Assignment operators
65   nsHtml5StreamParserPtr& operator=(const nsHtml5StreamParserPtr& rhs)
66   // copy assignment operator
67   {
68     assign_with_AddRef(rhs.mRawPtr);
69     return *this;
70   }
71   nsHtml5StreamParserPtr& operator=(nsHtml5StreamParser* rhs)
72   // assign from a raw pointer (of the right type)
73   {
74     assign_with_AddRef(rhs);
75     return *this;
76   }
77   // Other pointer operators
swap(nsHtml5StreamParserPtr & rhs)78   void swap(nsHtml5StreamParserPtr& rhs)
79   // ...exchange ownership with |rhs|; can save a pair of refcount operations
80   {
81     nsHtml5StreamParser* temp = rhs.mRawPtr;
82     rhs.mRawPtr = mRawPtr;
83     mRawPtr = temp;
84   }
swap(nsHtml5StreamParser * & rhs)85   void swap(nsHtml5StreamParser*& rhs)
86   // ...exchange ownership with |rhs|; can save a pair of refcount operations
87   {
88     nsHtml5StreamParser* temp = rhs;
89     rhs = mRawPtr;
90     mRawPtr = temp;
91   }
92   template <typename I>
forget(I ** rhs)93   void forget(I** rhs)
94   // Set the target of rhs to the value of mRawPtr and null out mRawPtr.
95   // Useful to avoid unnecessary AddRef/Release pairs with "out"
96   // parameters where rhs bay be a T** or an I** where I is a base class
97   // of T.
98   {
99     NS_ASSERTION(rhs, "Null pointer passed to forget!");
100     *rhs = mRawPtr;
101     mRawPtr = 0;
102   }
get()103   nsHtml5StreamParser* get() const
104   /*
105             Prefer the implicit conversion provided automatically by |operator
106      nsHtml5StreamParser*() const|. Use |get()| to resolve ambiguity or to get a
107      castable pointer.
108           */
109   {
110     return const_cast<nsHtml5StreamParser*>(mRawPtr);
111   }
112   operator nsHtml5StreamParser*() const
113   /*
114             ...makes an |nsHtml5StreamParserPtr| act like its underlying raw
115      pointer type whenever it is used in a context where a raw pointer is
116      expected.  It is this operator that makes an |nsHtml5StreamParserPtr|
117      substitutable for a raw pointer. Prefer the implicit use of this operator
118      to calling |get()|, except where necessary to resolve ambiguity.
119           */
120   {
121     return get();
122   }
123   nsHtml5StreamParser* operator->() const MOZ_NO_ADDREF_RELEASE_ON_RETURN {
124     MOZ_ASSERT(mRawPtr != 0,
125                "You can't dereference a NULL nsHtml5StreamParserPtr with "
126                "operator->().");
127     return get();
128   }
get_address()129   nsHtml5StreamParserPtr* get_address()
130   // This is not intended to be used by clients.  See |address_of|
131   // below.
132   {
133     return this;
134   }
get_address()135   const nsHtml5StreamParserPtr* get_address() const
136   // This is not intended to be used by clients.  See |address_of|
137   // below.
138   {
139     return this;
140   }
141 
142  public:
143   nsHtml5StreamParser& operator*() const {
144     MOZ_ASSERT(mRawPtr != 0,
145                "You can't dereference a NULL nsHtml5StreamParserPtr with "
146                "operator*().");
147     return *get();
148   }
StartAssignment()149   nsHtml5StreamParser** StartAssignment() {
150 #ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT
151     return reinterpret_cast<nsHtml5StreamParser**>(begin_assignment());
152 #else
153     assign_assuming_AddRef(0);
154     return reinterpret_cast<nsHtml5StreamParser**>(&mRawPtr);
155 #endif
156   }
157 };
158 
address_of(nsHtml5StreamParserPtr & aPtr)159 inline nsHtml5StreamParserPtr* address_of(nsHtml5StreamParserPtr& aPtr) {
160   return aPtr.get_address();
161 }
162 
address_of(const nsHtml5StreamParserPtr & aPtr)163 inline const nsHtml5StreamParserPtr* address_of(
164     const nsHtml5StreamParserPtr& aPtr) {
165   return aPtr.get_address();
166 }
167 
168 class nsHtml5StreamParserPtrGetterAddRefs
169 /*
170       ...
171       This class is designed to be used for anonymous temporary objects in the
172       argument list of calls that return COM interface pointers, e.g.,
173         nsHtml5StreamParserPtr<IFoo> fooP;
174         ...->GetAddRefedPointer(getter_AddRefs(fooP))
175       DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE.  Use |getter_AddRefs()|
176    instead. When initialized with a |nsHtml5StreamParserPtr|, as in the example
177    above, it returns a |void**|, a |T**|, or an |nsISupports**| as needed, that
178    the outer call (|GetAddRefedPointer| in this case) can fill in. This type
179    should be a nested class inside |nsHtml5StreamParserPtr<T>|.
180     */
181 {
182  public:
nsHtml5StreamParserPtrGetterAddRefs(nsHtml5StreamParserPtr & aSmartPtr)183   explicit nsHtml5StreamParserPtrGetterAddRefs(
184       nsHtml5StreamParserPtr& aSmartPtr)
185       : mTargetSmartPtr(aSmartPtr) {
186     // nothing else to do
187   }
188   operator void**() {
189     return reinterpret_cast<void**>(mTargetSmartPtr.StartAssignment());
190   }
191   operator nsHtml5StreamParser**() { return mTargetSmartPtr.StartAssignment(); }
192   nsHtml5StreamParser*& operator*() {
193     return *(mTargetSmartPtr.StartAssignment());
194   }
195 
196  private:
197   nsHtml5StreamParserPtr& mTargetSmartPtr;
198 };
199 
getter_AddRefs(nsHtml5StreamParserPtr & aSmartPtr)200 inline nsHtml5StreamParserPtrGetterAddRefs getter_AddRefs(
201     nsHtml5StreamParserPtr& aSmartPtr)
202 /*
203       Used around a |nsHtml5StreamParserPtr| when
204       ...makes the class |nsHtml5StreamParserPtrGetterAddRefs| invisible.
205     */
206 {
207   return nsHtml5StreamParserPtrGetterAddRefs(aSmartPtr);
208 }
209 
210 // Comparing an |nsHtml5StreamParserPtr| to |0|
211 
212 inline bool operator==(const nsHtml5StreamParserPtr& lhs, decltype(nullptr)) {
213   return lhs.get() == nullptr;
214 }
215 
216 inline bool operator==(decltype(nullptr), const nsHtml5StreamParserPtr& rhs) {
217   return nullptr == rhs.get();
218 }
219 
220 inline bool operator!=(const nsHtml5StreamParserPtr& lhs, decltype(nullptr)) {
221   return lhs.get() != nullptr;
222 }
223 
224 inline bool operator!=(decltype(nullptr), const nsHtml5StreamParserPtr& rhs) {
225   return nullptr != rhs.get();
226 }
227 
228 #endif  // !defined(nsHtml5StreamParserPtr_h)
229