Bug 1866777 - Disable test_race_cache_with_network.js on windows opt for frequent...
[gecko.git] / xpcom / ds / nsCOMArray.cpp
bloba7ce778e5c1a48f8064b7001b0704526e0cc68cd
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 #include "nsCOMArray.h"
9 #include "mozilla/MemoryReporting.h"
10 #include "mozilla/OperatorNewExtensions.h"
12 #include "nsCOMPtr.h"
14 // This specialization is private to nsCOMArray.
15 // It exists solely to automatically zero-out newly created array elements.
16 template <>
17 class nsTArrayElementTraits<nsISupports*> {
18 typedef nsISupports* E;
20 public:
21 // Zero out the value
22 static inline void Construct(E* aE) {
23 new (mozilla::KnownNotNull, static_cast<void*>(aE)) E();
25 // Invoke the copy-constructor in place.
26 template <class A>
27 static inline void Construct(E* aE, const A& aArg) {
28 new (mozilla::KnownNotNull, static_cast<void*>(aE)) E(aArg);
30 // Construct in place.
31 template <class... Args>
32 static inline void Emplace(E* aE, Args&&... aArgs) {
33 new (mozilla::KnownNotNull, static_cast<void*>(aE))
34 E(std::forward<Args>(aArgs)...);
36 // Invoke the destructor in place.
37 static inline void Destruct(E* aE) { aE->~E(); }
40 static void ReleaseObjects(nsTArray<nsISupports*>& aArray);
42 // implementations of non-trivial methods in nsCOMArray_base
44 nsCOMArray_base::nsCOMArray_base(const nsCOMArray_base& aOther) {
45 // make sure we do only one allocation
46 mArray.SetCapacity(aOther.Count());
47 AppendObjects(aOther);
50 nsCOMArray_base::~nsCOMArray_base() { Clear(); }
52 int32_t nsCOMArray_base::IndexOf(nsISupports* aObject,
53 uint32_t aStartIndex) const {
54 return mArray.IndexOf(aObject, aStartIndex);
57 int32_t nsCOMArray_base::IndexOfObject(nsISupports* aObject) const {
58 nsCOMPtr<nsISupports> supports = do_QueryInterface(aObject);
59 if (NS_WARN_IF(!supports)) {
60 return -1;
63 uint32_t i, count;
64 int32_t retval = -1;
65 count = mArray.Length();
66 for (i = 0; i < count; ++i) {
67 nsCOMPtr<nsISupports> arrayItem = do_QueryInterface(mArray[i]);
68 if (arrayItem == supports) {
69 retval = i;
70 break;
73 return retval;
76 bool nsCOMArray_base::EnumerateForwards(nsBaseArrayEnumFunc aFunc,
77 void* aData) const {
78 for (uint32_t index = 0; index < mArray.Length(); ++index) {
79 if (!(*aFunc)(mArray[index], aData)) {
80 return false;
84 return true;
87 bool nsCOMArray_base::EnumerateBackwards(nsBaseArrayEnumFunc aFunc,
88 void* aData) const {
89 for (uint32_t index = mArray.Length(); index--;) {
90 if (!(*aFunc)(mArray[index], aData)) {
91 return false;
95 return true;
98 bool nsCOMArray_base::InsertObjectAt(nsISupports* aObject, int32_t aIndex) {
99 if ((uint32_t)aIndex > mArray.Length()) {
100 return false;
103 mArray.InsertElementAt(aIndex, aObject);
105 NS_IF_ADDREF(aObject);
106 return true;
109 void nsCOMArray_base::InsertElementAt(uint32_t aIndex, nsISupports* aElement) {
110 mArray.InsertElementAt(aIndex, aElement);
111 NS_IF_ADDREF(aElement);
114 void nsCOMArray_base::InsertElementAt(uint32_t aIndex,
115 already_AddRefed<nsISupports> aElement) {
116 mArray.InsertElementAt(aIndex, aElement.take());
119 bool nsCOMArray_base::InsertObjectsAt(const nsCOMArray_base& aObjects,
120 int32_t aIndex) {
121 if ((uint32_t)aIndex > mArray.Length()) {
122 return false;
125 mArray.InsertElementsAt(aIndex, aObjects.mArray);
127 // need to addref all these
128 uint32_t count = aObjects.Length();
129 for (uint32_t i = 0; i < count; ++i) {
130 NS_IF_ADDREF(aObjects[i]);
133 return true;
136 void nsCOMArray_base::InsertElementsAt(uint32_t aIndex,
137 const nsCOMArray_base& aElements) {
138 mArray.InsertElementsAt(aIndex, aElements.mArray);
140 // need to addref all these
141 uint32_t count = aElements.Length();
142 for (uint32_t i = 0; i < count; ++i) {
143 NS_IF_ADDREF(aElements[i]);
147 void nsCOMArray_base::InsertElementsAt(uint32_t aIndex,
148 nsISupports* const* aElements,
149 uint32_t aCount) {
150 mArray.InsertElementsAt(aIndex, aElements, aCount);
152 // need to addref all these
153 for (uint32_t i = 0; i < aCount; ++i) {
154 NS_IF_ADDREF(aElements[i]);
158 void nsCOMArray_base::ReplaceObjectAt(nsISupports* aObject, int32_t aIndex) {
159 mArray.EnsureLengthAtLeast(aIndex + 1);
160 nsISupports* oldObject = mArray[aIndex];
161 // Make sure to addref first, in case aObject == oldObject
162 NS_IF_ADDREF(mArray[aIndex] = aObject);
163 NS_IF_RELEASE(oldObject);
166 bool nsCOMArray_base::RemoveObject(nsISupports* aObject) {
167 bool result = mArray.RemoveElement(aObject);
168 if (result) {
169 NS_IF_RELEASE(aObject);
171 return result;
174 bool nsCOMArray_base::RemoveObjectAt(int32_t aIndex) {
175 if (uint32_t(aIndex) < mArray.Length()) {
176 nsISupports* element = mArray[aIndex];
178 mArray.RemoveElementAt(aIndex);
179 NS_IF_RELEASE(element);
180 return true;
183 return false;
186 void nsCOMArray_base::RemoveElementAt(uint32_t aIndex) {
187 nsISupports* element = mArray[aIndex];
188 mArray.RemoveElementAt(aIndex);
189 NS_IF_RELEASE(element);
192 bool nsCOMArray_base::RemoveObjectsAt(int32_t aIndex, int32_t aCount) {
193 if (uint32_t(aIndex) + uint32_t(aCount) <= mArray.Length()) {
194 nsTArray<nsISupports*> elementsToDestroy(aCount);
195 elementsToDestroy.AppendElements(mArray.Elements() + aIndex, aCount);
196 mArray.RemoveElementsAt(aIndex, aCount);
197 ReleaseObjects(elementsToDestroy);
198 return true;
201 return false;
204 void nsCOMArray_base::RemoveElementsAt(uint32_t aIndex, uint32_t aCount) {
205 nsTArray<nsISupports*> elementsToDestroy(aCount);
206 elementsToDestroy.AppendElements(mArray.Elements() + aIndex, aCount);
207 mArray.RemoveElementsAt(aIndex, aCount);
208 ReleaseObjects(elementsToDestroy);
211 // useful for destructors
212 void ReleaseObjects(nsTArray<nsISupports*>& aArray) {
213 for (uint32_t i = 0; i < aArray.Length(); ++i) {
214 NS_IF_RELEASE(aArray[i]);
218 void nsCOMArray_base::Clear() {
219 nsTArray<nsISupports*> objects = std::move(mArray);
220 ReleaseObjects(objects);
223 bool nsCOMArray_base::SetCount(int32_t aNewCount) {
224 NS_ASSERTION(aNewCount >= 0, "SetCount(negative index)");
225 if (aNewCount < 0) {
226 return false;
229 int32_t count = mArray.Length();
230 if (count > aNewCount) {
231 RemoveObjectsAt(aNewCount, mArray.Length() - aNewCount);
233 mArray.SetLength(aNewCount);
234 return true;