Tue, 06 Jan 2015 21:39:09 +0100
Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
michael@0 | 1 | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
michael@0 | 2 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 4 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 5 | |
michael@0 | 6 | #ifndef nsCOMArray_h__ |
michael@0 | 7 | #define nsCOMArray_h__ |
michael@0 | 8 | |
michael@0 | 9 | #include "mozilla/Attributes.h" |
michael@0 | 10 | #include "mozilla/MemoryReporting.h" |
michael@0 | 11 | |
michael@0 | 12 | #include "nsCycleCollectionNoteChild.h" |
michael@0 | 13 | #include "nsTArray.h" |
michael@0 | 14 | #include "nsISupports.h" |
michael@0 | 15 | |
michael@0 | 16 | // See below for the definition of nsCOMArray<T> |
michael@0 | 17 | |
michael@0 | 18 | // a class that's nsISupports-specific, so that we can contain the |
michael@0 | 19 | // work of this class in the XPCOM dll |
michael@0 | 20 | class NS_COM_GLUE nsCOMArray_base |
michael@0 | 21 | { |
michael@0 | 22 | friend class nsArray; |
michael@0 | 23 | protected: |
michael@0 | 24 | nsCOMArray_base() {} |
michael@0 | 25 | nsCOMArray_base(int32_t aCount) : mArray(aCount) {} |
michael@0 | 26 | nsCOMArray_base(const nsCOMArray_base& other); |
michael@0 | 27 | ~nsCOMArray_base(); |
michael@0 | 28 | |
michael@0 | 29 | int32_t IndexOf(nsISupports* aObject, uint32_t aStartIndex = 0) const; |
michael@0 | 30 | bool Contains(nsISupports* aObject) const { |
michael@0 | 31 | return IndexOf(aObject) != -1; |
michael@0 | 32 | } |
michael@0 | 33 | |
michael@0 | 34 | int32_t IndexOfObject(nsISupports* aObject) const; |
michael@0 | 35 | bool ContainsObject(nsISupports* aObject) const { |
michael@0 | 36 | return IndexOfObject(aObject) != -1; |
michael@0 | 37 | } |
michael@0 | 38 | |
michael@0 | 39 | typedef bool (* nsBaseArrayEnumFunc) |
michael@0 | 40 | (void* aElement, void *aData); |
michael@0 | 41 | |
michael@0 | 42 | // enumerate through the array with a callback. |
michael@0 | 43 | bool EnumerateForwards(nsBaseArrayEnumFunc aFunc, void* aData) const; |
michael@0 | 44 | |
michael@0 | 45 | bool EnumerateBackwards(nsBaseArrayEnumFunc aFunc, void* aData) const; |
michael@0 | 46 | |
michael@0 | 47 | typedef int (* nsBaseArrayComparatorFunc) |
michael@0 | 48 | (nsISupports* aElement1, nsISupports* aElement2, void* aData); |
michael@0 | 49 | |
michael@0 | 50 | struct nsCOMArrayComparatorContext { |
michael@0 | 51 | nsBaseArrayComparatorFunc mComparatorFunc; |
michael@0 | 52 | void* mData; |
michael@0 | 53 | }; |
michael@0 | 54 | |
michael@0 | 55 | static int nsCOMArrayComparator(const void* aElement1, const void* aElement2, void* aData); |
michael@0 | 56 | void Sort(nsBaseArrayComparatorFunc aFunc, void* aData); |
michael@0 | 57 | |
michael@0 | 58 | bool InsertObjectAt(nsISupports* aObject, int32_t aIndex); |
michael@0 | 59 | void InsertElementAt(uint32_t aIndex, nsISupports* aElement); |
michael@0 | 60 | bool InsertObjectsAt(const nsCOMArray_base& aObjects, int32_t aIndex); |
michael@0 | 61 | void InsertElementsAt(uint32_t aIndex, const nsCOMArray_base& aElements); |
michael@0 | 62 | void InsertElementsAt(uint32_t aIndex, nsISupports* const* aElements, uint32_t aCount); |
michael@0 | 63 | bool ReplaceObjectAt(nsISupports* aObject, int32_t aIndex); |
michael@0 | 64 | void ReplaceElementAt(uint32_t aIndex, nsISupports* aElement) { |
michael@0 | 65 | nsISupports* oldElement = mArray[aIndex]; |
michael@0 | 66 | NS_IF_ADDREF(mArray[aIndex] = aElement); |
michael@0 | 67 | NS_IF_RELEASE(oldElement); |
michael@0 | 68 | } |
michael@0 | 69 | bool AppendObject(nsISupports *aObject) { |
michael@0 | 70 | return InsertObjectAt(aObject, Count()); |
michael@0 | 71 | } |
michael@0 | 72 | void AppendElement(nsISupports* aElement) { |
michael@0 | 73 | InsertElementAt(Length(), aElement); |
michael@0 | 74 | } |
michael@0 | 75 | bool AppendObjects(const nsCOMArray_base& aObjects) { |
michael@0 | 76 | return InsertObjectsAt(aObjects, Count()); |
michael@0 | 77 | } |
michael@0 | 78 | void AppendElements(const nsCOMArray_base& aElements) { |
michael@0 | 79 | return InsertElementsAt(Length(), aElements); |
michael@0 | 80 | } |
michael@0 | 81 | void AppendElements(nsISupports* const* aElements, uint32_t aCount) { |
michael@0 | 82 | return InsertElementsAt(Length(), aElements, aCount); |
michael@0 | 83 | } |
michael@0 | 84 | bool RemoveObject(nsISupports *aObject); |
michael@0 | 85 | nsISupports** Elements() { |
michael@0 | 86 | return mArray.Elements(); |
michael@0 | 87 | } |
michael@0 | 88 | void SwapElements(nsCOMArray_base& aOther) { |
michael@0 | 89 | mArray.SwapElements(aOther.mArray); |
michael@0 | 90 | } |
michael@0 | 91 | |
michael@0 | 92 | void Adopt(nsISupports** aElements, uint32_t aCount); |
michael@0 | 93 | uint32_t Forget(nsISupports*** aElements); |
michael@0 | 94 | public: |
michael@0 | 95 | // elements in the array (including null elements!) |
michael@0 | 96 | int32_t Count() const { |
michael@0 | 97 | return mArray.Length(); |
michael@0 | 98 | } |
michael@0 | 99 | // nsTArray-compatible version |
michael@0 | 100 | uint32_t Length() const { |
michael@0 | 101 | return mArray.Length(); |
michael@0 | 102 | } |
michael@0 | 103 | bool IsEmpty() const { |
michael@0 | 104 | return mArray.IsEmpty(); |
michael@0 | 105 | } |
michael@0 | 106 | |
michael@0 | 107 | // If the array grows, the newly created entries will all be null; |
michael@0 | 108 | // if the array shrinks, the excess entries will all be released. |
michael@0 | 109 | bool SetCount(int32_t aNewCount); |
michael@0 | 110 | // nsTArray-compatible version |
michael@0 | 111 | void TruncateLength(uint32_t aNewLength) { |
michael@0 | 112 | if (mArray.Length() > aNewLength) |
michael@0 | 113 | RemoveElementsAt(aNewLength, mArray.Length() - aNewLength); |
michael@0 | 114 | } |
michael@0 | 115 | |
michael@0 | 116 | // remove all elements in the array, and call NS_RELEASE on each one |
michael@0 | 117 | void Clear(); |
michael@0 | 118 | |
michael@0 | 119 | nsISupports* ObjectAt(int32_t aIndex) const { |
michael@0 | 120 | return mArray[aIndex]; |
michael@0 | 121 | } |
michael@0 | 122 | // nsTArray-compatible version |
michael@0 | 123 | nsISupports* ElementAt(uint32_t aIndex) const { |
michael@0 | 124 | return mArray[aIndex]; |
michael@0 | 125 | } |
michael@0 | 126 | |
michael@0 | 127 | nsISupports* SafeObjectAt(int32_t aIndex) const { |
michael@0 | 128 | return mArray.SafeElementAt(aIndex, nullptr); |
michael@0 | 129 | } |
michael@0 | 130 | // nsTArray-compatible version |
michael@0 | 131 | nsISupports* SafeElementAt(uint32_t aIndex) const { |
michael@0 | 132 | return mArray.SafeElementAt(aIndex, nullptr); |
michael@0 | 133 | } |
michael@0 | 134 | |
michael@0 | 135 | nsISupports* operator[](int32_t aIndex) const { |
michael@0 | 136 | return mArray[aIndex]; |
michael@0 | 137 | } |
michael@0 | 138 | |
michael@0 | 139 | // remove an element at a specific position, shrinking the array |
michael@0 | 140 | // as necessary |
michael@0 | 141 | bool RemoveObjectAt(int32_t aIndex); |
michael@0 | 142 | // nsTArray-compatible version |
michael@0 | 143 | void RemoveElementAt(uint32_t aIndex); |
michael@0 | 144 | |
michael@0 | 145 | // remove a range of elements at a specific position, shrinking the array |
michael@0 | 146 | // as necessary |
michael@0 | 147 | bool RemoveObjectsAt(int32_t aIndex, int32_t aCount); |
michael@0 | 148 | // nsTArray-compatible version |
michael@0 | 149 | void RemoveElementsAt(uint32_t aIndex, uint32_t aCount); |
michael@0 | 150 | |
michael@0 | 151 | void SwapElementsAt(uint32_t aIndex1, uint32_t aIndex2) { |
michael@0 | 152 | nsISupports *tmp = mArray[aIndex1]; |
michael@0 | 153 | mArray[aIndex1] = mArray[aIndex2]; |
michael@0 | 154 | mArray[aIndex2] = tmp; |
michael@0 | 155 | } |
michael@0 | 156 | |
michael@0 | 157 | // Ensures there is enough space to store a total of aCapacity objects. |
michael@0 | 158 | // This method never deletes any objects. |
michael@0 | 159 | void SetCapacity(uint32_t aCapacity) { |
michael@0 | 160 | mArray.SetCapacity(aCapacity); |
michael@0 | 161 | } |
michael@0 | 162 | uint32_t Capacity() { |
michael@0 | 163 | return mArray.Capacity(); |
michael@0 | 164 | } |
michael@0 | 165 | |
michael@0 | 166 | typedef size_t (* nsBaseArraySizeOfElementIncludingThisFunc) |
michael@0 | 167 | (nsISupports* aElement, mozilla::MallocSizeOf aMallocSizeOf, void *aData); |
michael@0 | 168 | |
michael@0 | 169 | // Measures the size of the array's element storage, and if |
michael@0 | 170 | // |aSizeOfElement| is non-nullptr, measures the size of things pointed to |
michael@0 | 171 | // by elements. |
michael@0 | 172 | size_t SizeOfExcludingThis( |
michael@0 | 173 | nsBaseArraySizeOfElementIncludingThisFunc aSizeOfElementIncludingThis, |
michael@0 | 174 | mozilla::MallocSizeOf aMallocSizeOf, void* aData = nullptr) const; |
michael@0 | 175 | |
michael@0 | 176 | private: |
michael@0 | 177 | |
michael@0 | 178 | // the actual storage |
michael@0 | 179 | nsTArray<nsISupports*> mArray; |
michael@0 | 180 | |
michael@0 | 181 | // don't implement these, defaults will muck with refcounts! |
michael@0 | 182 | nsCOMArray_base& operator=(const nsCOMArray_base& other) MOZ_DELETE; |
michael@0 | 183 | }; |
michael@0 | 184 | |
michael@0 | 185 | inline void |
michael@0 | 186 | ImplCycleCollectionUnlink(nsCOMArray_base& aField) |
michael@0 | 187 | { |
michael@0 | 188 | aField.Clear(); |
michael@0 | 189 | } |
michael@0 | 190 | |
michael@0 | 191 | inline void |
michael@0 | 192 | ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback, |
michael@0 | 193 | nsCOMArray_base& aField, |
michael@0 | 194 | const char* aName, |
michael@0 | 195 | uint32_t aFlags = 0) |
michael@0 | 196 | { |
michael@0 | 197 | aFlags |= CycleCollectionEdgeNameArrayFlag; |
michael@0 | 198 | int32_t length = aField.Count(); |
michael@0 | 199 | for (int32_t i = 0; i < length; ++i) { |
michael@0 | 200 | CycleCollectionNoteChild(aCallback, aField[i], aName, aFlags); |
michael@0 | 201 | } |
michael@0 | 202 | } |
michael@0 | 203 | |
michael@0 | 204 | |
michael@0 | 205 | // a non-XPCOM, refcounting array of XPCOM objects |
michael@0 | 206 | // used as a member variable or stack variable - this object is NOT |
michael@0 | 207 | // refcounted, but the objects that it holds are |
michael@0 | 208 | // |
michael@0 | 209 | // most of the read-only accessors like ObjectAt()/etc do NOT refcount |
michael@0 | 210 | // on the way out. This means that you can do one of two things: |
michael@0 | 211 | // |
michael@0 | 212 | // * does an addref, but holds onto a reference |
michael@0 | 213 | // nsCOMPtr<T> foo = array[i]; |
michael@0 | 214 | // |
michael@0 | 215 | // * avoids the refcount, but foo might go stale if array[i] is ever |
michael@0 | 216 | // * modified/removed. Be careful not to NS_RELEASE(foo)! |
michael@0 | 217 | // T* foo = array[i]; |
michael@0 | 218 | // |
michael@0 | 219 | // This array will accept null as an argument for any object, and will |
michael@0 | 220 | // store null in the array, just like nsVoidArray. But that also means |
michael@0 | 221 | // that methods like ObjectAt() may return null when referring to an |
michael@0 | 222 | // existing, but null entry in the array. |
michael@0 | 223 | template <class T> |
michael@0 | 224 | class nsCOMArray : public nsCOMArray_base |
michael@0 | 225 | { |
michael@0 | 226 | public: |
michael@0 | 227 | nsCOMArray() {} |
michael@0 | 228 | |
michael@0 | 229 | explicit |
michael@0 | 230 | nsCOMArray(int32_t aCount) : nsCOMArray_base(aCount) {} |
michael@0 | 231 | |
michael@0 | 232 | explicit |
michael@0 | 233 | nsCOMArray(const nsCOMArray<T>& aOther) : nsCOMArray_base(aOther) { } |
michael@0 | 234 | |
michael@0 | 235 | nsCOMArray(nsCOMArray<T>&& aOther) { SwapElements(aOther); } |
michael@0 | 236 | |
michael@0 | 237 | ~nsCOMArray() {} |
michael@0 | 238 | |
michael@0 | 239 | // We have a move assignment operator, but no copy assignment operator. |
michael@0 | 240 | nsCOMArray<T>& operator=(nsCOMArray<T>&& aOther) { |
michael@0 | 241 | SwapElements(aOther); |
michael@0 | 242 | return *this; |
michael@0 | 243 | } |
michael@0 | 244 | |
michael@0 | 245 | // these do NOT refcount on the way out, for speed |
michael@0 | 246 | T* ObjectAt(int32_t aIndex) const { |
michael@0 | 247 | return static_cast<T*>(nsCOMArray_base::ObjectAt(aIndex)); |
michael@0 | 248 | } |
michael@0 | 249 | // nsTArray-compatible version |
michael@0 | 250 | T* ElementAt(uint32_t aIndex) const { |
michael@0 | 251 | return static_cast<T*>(nsCOMArray_base::ElementAt(aIndex)); |
michael@0 | 252 | } |
michael@0 | 253 | |
michael@0 | 254 | // these do NOT refcount on the way out, for speed |
michael@0 | 255 | T* SafeObjectAt(int32_t aIndex) const { |
michael@0 | 256 | return static_cast<T*>(nsCOMArray_base::SafeObjectAt(aIndex)); |
michael@0 | 257 | } |
michael@0 | 258 | // nsTArray-compatible version |
michael@0 | 259 | T* SafeElementAt(uint32_t aIndex) const { |
michael@0 | 260 | return static_cast<T*>(nsCOMArray_base::SafeElementAt(aIndex)); |
michael@0 | 261 | } |
michael@0 | 262 | |
michael@0 | 263 | // indexing operator for syntactic sugar |
michael@0 | 264 | T* operator[](int32_t aIndex) const { |
michael@0 | 265 | return ObjectAt(aIndex); |
michael@0 | 266 | } |
michael@0 | 267 | |
michael@0 | 268 | // index of the element in question.. does NOT refcount |
michael@0 | 269 | // note: this does not check COM object identity. Use |
michael@0 | 270 | // IndexOfObject() for that purpose |
michael@0 | 271 | int32_t IndexOf(T* aObject, uint32_t aStartIndex = 0) const { |
michael@0 | 272 | return nsCOMArray_base::IndexOf(aObject, aStartIndex); |
michael@0 | 273 | } |
michael@0 | 274 | bool Contains(nsISupports* aObject) const { |
michael@0 | 275 | return nsCOMArray_base::Contains(aObject); |
michael@0 | 276 | } |
michael@0 | 277 | |
michael@0 | 278 | // index of the element in question.. be careful! |
michael@0 | 279 | // this is much slower than IndexOf() because it uses |
michael@0 | 280 | // QueryInterface to determine actual COM identity of the object |
michael@0 | 281 | // if you need to do this frequently then consider enforcing |
michael@0 | 282 | // COM object identity before adding/comparing elements |
michael@0 | 283 | int32_t IndexOfObject(T* aObject) const { |
michael@0 | 284 | return nsCOMArray_base::IndexOfObject(aObject); |
michael@0 | 285 | } |
michael@0 | 286 | bool ContainsObject(nsISupports* aObject) const { |
michael@0 | 287 | return nsCOMArray_base::ContainsObject(aObject); |
michael@0 | 288 | } |
michael@0 | 289 | |
michael@0 | 290 | // inserts aObject at aIndex, shifting the objects at aIndex and |
michael@0 | 291 | // later to make space |
michael@0 | 292 | bool InsertObjectAt(T* aObject, int32_t aIndex) { |
michael@0 | 293 | return nsCOMArray_base::InsertObjectAt(aObject, aIndex); |
michael@0 | 294 | } |
michael@0 | 295 | // nsTArray-compatible version |
michael@0 | 296 | void InsertElementAt(uint32_t aIndex, T* aElement) { |
michael@0 | 297 | nsCOMArray_base::InsertElementAt(aIndex, aElement); |
michael@0 | 298 | } |
michael@0 | 299 | |
michael@0 | 300 | // inserts the objects from aObject at aIndex, shifting the |
michael@0 | 301 | // objects at aIndex and later to make space |
michael@0 | 302 | bool InsertObjectsAt(const nsCOMArray<T>& aObjects, int32_t aIndex) { |
michael@0 | 303 | return nsCOMArray_base::InsertObjectsAt(aObjects, aIndex); |
michael@0 | 304 | } |
michael@0 | 305 | // nsTArray-compatible version |
michael@0 | 306 | void InsertElementsAt(uint32_t aIndex, const nsCOMArray<T>& aElements) { |
michael@0 | 307 | nsCOMArray_base::InsertElementsAt(aIndex, aElements); |
michael@0 | 308 | } |
michael@0 | 309 | void InsertElementsAt(uint32_t aIndex, T* const* aElements, uint32_t aCount) { |
michael@0 | 310 | nsCOMArray_base::InsertElementsAt(aIndex, reinterpret_cast<nsISupports* const*>(aElements), aCount); |
michael@0 | 311 | } |
michael@0 | 312 | |
michael@0 | 313 | // replaces an existing element. Warning: if the array grows, |
michael@0 | 314 | // the newly created entries will all be null |
michael@0 | 315 | bool ReplaceObjectAt(T* aObject, int32_t aIndex) { |
michael@0 | 316 | return nsCOMArray_base::ReplaceObjectAt(aObject, aIndex); |
michael@0 | 317 | } |
michael@0 | 318 | // nsTArray-compatible version |
michael@0 | 319 | void ReplaceElementAt(uint32_t aIndex, T* aElement) { |
michael@0 | 320 | nsCOMArray_base::ReplaceElementAt(aIndex, aElement); |
michael@0 | 321 | } |
michael@0 | 322 | |
michael@0 | 323 | // Enumerator callback function. Return false to stop |
michael@0 | 324 | // Here's a more readable form: |
michael@0 | 325 | // bool enumerate(T* aElement, void* aData) |
michael@0 | 326 | typedef bool (* nsCOMArrayEnumFunc) |
michael@0 | 327 | (T* aElement, void *aData); |
michael@0 | 328 | |
michael@0 | 329 | // enumerate through the array with a callback. |
michael@0 | 330 | bool EnumerateForwards(nsCOMArrayEnumFunc aFunc, void* aData) { |
michael@0 | 331 | return nsCOMArray_base::EnumerateForwards(nsBaseArrayEnumFunc(aFunc), |
michael@0 | 332 | aData); |
michael@0 | 333 | } |
michael@0 | 334 | |
michael@0 | 335 | bool EnumerateBackwards(nsCOMArrayEnumFunc aFunc, void* aData) { |
michael@0 | 336 | return nsCOMArray_base::EnumerateBackwards(nsBaseArrayEnumFunc(aFunc), |
michael@0 | 337 | aData); |
michael@0 | 338 | } |
michael@0 | 339 | |
michael@0 | 340 | typedef int (* nsCOMArrayComparatorFunc) |
michael@0 | 341 | (T* aElement1, T* aElement2, void* aData); |
michael@0 | 342 | |
michael@0 | 343 | void Sort(nsCOMArrayComparatorFunc aFunc, void* aData) { |
michael@0 | 344 | nsCOMArray_base::Sort(nsBaseArrayComparatorFunc(aFunc), aData); |
michael@0 | 345 | } |
michael@0 | 346 | |
michael@0 | 347 | // append an object, growing the array as necessary |
michael@0 | 348 | bool AppendObject(T *aObject) { |
michael@0 | 349 | return nsCOMArray_base::AppendObject(aObject); |
michael@0 | 350 | } |
michael@0 | 351 | // nsTArray-compatible version |
michael@0 | 352 | void AppendElement(T* aElement) { |
michael@0 | 353 | nsCOMArray_base::AppendElement(aElement); |
michael@0 | 354 | } |
michael@0 | 355 | |
michael@0 | 356 | // append objects, growing the array as necessary |
michael@0 | 357 | bool AppendObjects(const nsCOMArray<T>& aObjects) { |
michael@0 | 358 | return nsCOMArray_base::AppendObjects(aObjects); |
michael@0 | 359 | } |
michael@0 | 360 | // nsTArray-compatible version |
michael@0 | 361 | void AppendElements(const nsCOMArray<T>& aElements) { |
michael@0 | 362 | return nsCOMArray_base::AppendElements(aElements); |
michael@0 | 363 | } |
michael@0 | 364 | void AppendElements(T* const* aElements, uint32_t aCount) { |
michael@0 | 365 | InsertElementsAt(Length(), aElements, aCount); |
michael@0 | 366 | } |
michael@0 | 367 | |
michael@0 | 368 | // remove the first instance of the given object and shrink the |
michael@0 | 369 | // array as necessary |
michael@0 | 370 | // Warning: if you pass null here, it will remove the first null element |
michael@0 | 371 | bool RemoveObject(T *aObject) { |
michael@0 | 372 | return nsCOMArray_base::RemoveObject(aObject); |
michael@0 | 373 | } |
michael@0 | 374 | // nsTArray-compatible version |
michael@0 | 375 | bool RemoveElement(T* aElement) { |
michael@0 | 376 | return nsCOMArray_base::RemoveObject(aElement); |
michael@0 | 377 | } |
michael@0 | 378 | |
michael@0 | 379 | T** Elements() { |
michael@0 | 380 | return reinterpret_cast<T**>(nsCOMArray_base::Elements()); |
michael@0 | 381 | } |
michael@0 | 382 | void SwapElements(nsCOMArray<T>& aOther) { |
michael@0 | 383 | nsCOMArray_base::SwapElements(aOther); |
michael@0 | 384 | } |
michael@0 | 385 | |
michael@0 | 386 | // Each element in an nsCOMArray<T> is actually a T*, so this function is |
michael@0 | 387 | // "IncludingThis" rather than "ExcludingThis" because it needs to measure |
michael@0 | 388 | // the memory taken by the T itself as well as anything it points to. |
michael@0 | 389 | typedef size_t (* nsCOMArraySizeOfElementIncludingThisFunc) |
michael@0 | 390 | (T* aElement, mozilla::MallocSizeOf aMallocSizeOf, void *aData); |
michael@0 | 391 | |
michael@0 | 392 | size_t SizeOfExcludingThis( |
michael@0 | 393 | nsCOMArraySizeOfElementIncludingThisFunc aSizeOfElementIncludingThis, |
michael@0 | 394 | mozilla::MallocSizeOf aMallocSizeOf, void *aData = nullptr) const { |
michael@0 | 395 | return nsCOMArray_base::SizeOfExcludingThis( |
michael@0 | 396 | nsBaseArraySizeOfElementIncludingThisFunc(aSizeOfElementIncludingThis), |
michael@0 | 397 | aMallocSizeOf, aData); |
michael@0 | 398 | } |
michael@0 | 399 | |
michael@0 | 400 | /** |
michael@0 | 401 | * Adopt parameters that resulted from an XPIDL outparam. The aElements |
michael@0 | 402 | * parameter will be freed as a result of the call. |
michael@0 | 403 | * |
michael@0 | 404 | * Example usage: |
michael@0 | 405 | * nsCOMArray<nsISomeInterface> array; |
michael@0 | 406 | * nsISomeInterface** elements; |
michael@0 | 407 | * uint32_t length; |
michael@0 | 408 | * ptr->GetSomeArray(&elements, &length); |
michael@0 | 409 | * array.Adopt(elements, length); |
michael@0 | 410 | */ |
michael@0 | 411 | void Adopt(T** aElements, uint32_t aSize) { |
michael@0 | 412 | nsCOMArray_base::Adopt(reinterpret_cast<nsISupports**>(aElements), |
michael@0 | 413 | aSize); |
michael@0 | 414 | } |
michael@0 | 415 | |
michael@0 | 416 | /** |
michael@0 | 417 | * Export the contents of this array to an XPIDL outparam. The array will be |
michael@0 | 418 | * Clear()'d after this operation. |
michael@0 | 419 | * |
michael@0 | 420 | * Example usage: |
michael@0 | 421 | * nsCOMArray<nsISomeInterface> array; |
michael@0 | 422 | * *length = array.Forget(retval); |
michael@0 | 423 | */ |
michael@0 | 424 | uint32_t Forget(T*** elements) { |
michael@0 | 425 | return nsCOMArray_base::Forget( |
michael@0 | 426 | reinterpret_cast<nsISupports***>(elements)); |
michael@0 | 427 | } |
michael@0 | 428 | |
michael@0 | 429 | private: |
michael@0 | 430 | |
michael@0 | 431 | // don't implement these! |
michael@0 | 432 | nsCOMArray<T>& operator=(const nsCOMArray<T>& other) MOZ_DELETE; |
michael@0 | 433 | }; |
michael@0 | 434 | |
michael@0 | 435 | template <typename T> |
michael@0 | 436 | inline void |
michael@0 | 437 | ImplCycleCollectionUnlink(nsCOMArray<T>& aField) |
michael@0 | 438 | { |
michael@0 | 439 | aField.Clear(); |
michael@0 | 440 | } |
michael@0 | 441 | |
michael@0 | 442 | template <typename E> |
michael@0 | 443 | inline void |
michael@0 | 444 | ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback, |
michael@0 | 445 | nsCOMArray<E>& aField, |
michael@0 | 446 | const char* aName, |
michael@0 | 447 | uint32_t aFlags = 0) |
michael@0 | 448 | { |
michael@0 | 449 | aFlags |= CycleCollectionEdgeNameArrayFlag; |
michael@0 | 450 | int32_t length = aField.Count(); |
michael@0 | 451 | for (int32_t i = 0; i < length; ++i) { |
michael@0 | 452 | CycleCollectionNoteChild(aCallback, aField[i], aName, aFlags); |
michael@0 | 453 | } |
michael@0 | 454 | } |
michael@0 | 455 | |
michael@0 | 456 | #endif |