1 /* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*- */
2 /* vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */
3 /* ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
16 * The Original Code is [Open Source Virtual Machine.].
18 * The Initial Developer of the Original Code is
19 * Adobe System Incorporated.
20 * Portions created by the Initial Developer are Copyright (C) 2004-2006
21 * the Initial Developer. All Rights Reserved.
26 * Alternatively, the contents of this file may be used under the terms of
27 * either the GNU General Public License Version 2 or later (the "GPL"), or
28 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
38 * ***** END LICENSE BLOCK ***** */
45 template<typename T
, int growthIncrement
=4>
49 BasicList() : count(0),
67 mmfx_delete_array(items
);
70 count
= capacity
= iteratorCount
= 0;
77 if (holes
&& iteratorCount
== 0)
79 if (count
== capacity
)
81 capacity
+= growthIncrement
;
82 T
* newItems
= mmfx_new_array_opt(T
, capacity
, kZero
);
84 VMPI_memcpy(newItems
, items
, count
* sizeof(T
));
85 mmfx_delete_array(items
);
88 uint32_t numHoles
= 0;
91 uint32_t numFound
= 0;
92 for (uint32_t j
= 0; numFound
< count
&& j
< capacity
; j
++)
102 items
[count
+numHoles
] = item
;
108 if (holes
&& iteratorCount
== 0)
110 if (count
== capacity
)
112 uint32_t tryCapacity
= capacity
+ growthIncrement
;
113 T
* newItems
= mmfx_new_array_opt(T
, tryCapacity
, (MMgc::FixedMallocOpts
)(kZero
|kCanFail
));
115 if (newItems
== NULL
)
118 capacity
= tryCapacity
;
120 VMPI_memcpy(newItems
, items
, count
* sizeof(T
));
121 mmfx_delete_array(items
);
124 uint32_t numHoles
= 0;
127 uint32_t numFound
= 0;
128 for (uint32_t j
= 0; numFound
< count
&& j
< capacity
; j
++)
130 if (items
[j
] == NULL
)
138 items
[count
+numHoles
] = item
;
145 if (holes
&& iteratorCount
== 0)
148 while (i
< Limit() && items
[i
] != item
)
152 GCAssertMsg(false, "Bug: should not try to remove something that's not in the list");
156 // If the item we deleted occured is our cursor, set our cursor to the next item
161 }while (cursor
< capacity
&& items
[cursor
] == NULL
);
163 // If our "next item" is the last item, then reset the list to the front.
164 if (cursor
== capacity
)
176 T
Get(uint32_t i
) const
178 GCAssertMsg(i
< Limit(), "Index out of bounds");
182 // Call "SetCursor" on the list to have future iterators begin iterating from that position in the list.
183 // The iterator will still iterate through all items in the list once by wrapping to the front when the end is hit.
184 void SetCursor( uint32_t newCursor
) { cursor
= newCursor
;}
185 uint32_t GetCursor ( ){ return cursor
;}
186 uint32_t Count() const { return count
; }
188 // iterator needs this to give complete iteration in the face of in-flight mutation
189 uint32_t Limit() const { return holes
? capacity
: count
; }
191 void IteratorAttach() { iteratorCount
++; }
192 void IteratorDettach()
195 if (holes
&& iteratorCount
== 0)
201 BasicList(const BasicList
& other
);
202 BasicList
& operator=(const BasicList
& other
);
208 // i iterates through destintation slots and j iterates through source slots
209 // j skips over holes i doesn't
210 // at the end i = count
214 if (items
[i
] == NULL
)
216 if (items
[j
] != NULL
)
218 if (cursor
== j
) cursor
= i
;
219 items
[i
++] = items
[j
++];
220 items
[j
-1] = NULL
; // NULL it so next item goes in this hole
232 GCAssert(i
== count
);
236 uint32_t count
, capacity
;
238 uint32_t iteratorCount
;
244 // The BasicListIterator will iterate through items in the BasicList starting with the List's "cursor position"
245 // if "SetCursor" is never called on the BasicList passed into this BasicListIterator, then the list will iterate starting
246 // at position 0. The iterator will still iterate through all items in the list once by wrapping to the front when the end is hit.
248 class BasicListIterator
251 BasicListIterator(BasicList
<T
>& bl
) : bl(bl
), bListEnd(false)
253 index
= bl
.GetCursor();
259 bl
.IteratorDettach();
263 if (bListEnd
) return NULL
;
266 if (index
>= bl
.GetCursor())
268 // iterate over holes until end
269 while (index
< bl
.Limit() && t
== NULL
)
274 if (index
== bl
.Limit() && bl
.GetCursor() != 0)
281 while(index
< bl
.GetCursor() && t
== NULL
)
285 if (index
== bl
.GetCursor())
292 void MarkCursorInList()
294 while (index
< bl
.Limit() && bl
.Get(index
) == NULL
)
298 bl
.SetCursor( (index
< bl
.Limit()) ? index
: 0);
308 #endif /* __GCStack__ */