1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
12 // ArrayList is a simple class which is used to contain a growable
13 // list of pointers, stored in chunks. Modification is by appending
14 // only currently. Access is by index (efficient if the number of
15 // elements stays small) and iteration (efficient in all cases).
17 // An important property of an ArrayList is that the list remains
18 // coherent while it is being modified (appended to). This means that readers
19 // never need to lock when accessing it. (Locking is necessary among multiple
23 void ArrayListBase::Clear()
32 ArrayListBlock *block = m_firstBlock.m_next;
35 ArrayListBlock *next = block->m_next;
39 m_firstBlock.m_next = 0;
43 PTR_VOID * ArrayListBase::GetPtr(DWORD index) const
45 STATIC_CONTRACT_NOTHROW;
46 STATIC_CONTRACT_FORBID_FAULT;
47 STATIC_CONTRACT_CANNOT_TAKE_LOCK;
50 _ASSERTE(index < m_count);
52 ArrayListBlock *b = (ArrayListBlock*)&m_firstBlock;
53 while (index >= b->m_blockSize)
55 PREFIX_ASSUME(b->m_next != NULL);
56 index -= b->m_blockSize;
60 return b->m_array + index;
63 #ifndef DACCESS_COMPILE
65 HRESULT ArrayListBase::Append(void *element)
70 INJECT_FAULT(return E_OUTOFMEMORY;);
74 ArrayListBlock *b = (ArrayListBlock*)&m_firstBlock;
75 DWORD count = m_count;
77 while (count >= b->m_blockSize)
79 count -= b->m_blockSize;
81 if (b->m_next == NULL)
85 DWORD nextSize = b->m_blockSize * 2;
87 ArrayListBlock *bNew = (ArrayListBlock *)
88 new (nothrow) BYTE [sizeof(ArrayListBlock) + nextSize * sizeof(void*)];
94 bNew->m_blockSize = nextSize;
102 b->m_array[count] = element;
109 #endif // #ifndef DACCESS_COMPILE
111 DWORD ArrayListBase::FindElement(DWORD start, PTR_VOID element) const
122 _ASSERTE(index <= m_count);
124 ArrayListBlock *b = (ArrayListBlock*)&m_firstBlock;
127 // Skip to the block containing start.
128 // index should be the index of start in the block.
131 while (b != NULL && index >= b->m_blockSize)
133 index -= b->m_blockSize;
138 // Adjust start to be the index of the start of the block
144 // Compute max number of entries from the start of the block
147 DWORD max = m_count - start;
152 // Compute end of search in this block - either end of the block
153 // or end of the array
157 if (max < b->m_blockSize)
160 blockMax = b->m_blockSize;
163 // Scan for element, until the end.
166 while (index < blockMax)
168 if (b->m_array[index] == element)
169 return start + index;
174 // Otherwise, increment block start index, decrement max count,
175 // reset index, and go to the next block (if any)
178 start += b->m_blockSize;
179 max -= b->m_blockSize;
184 return (DWORD) NOT_FOUND;
187 BOOL ArrayListBase::Iterator::Next()
189 LIMITED_METHOD_DAC_CONTRACT;
193 if (m_index >= m_remaining)
196 if (m_index >= m_block->m_blockSize)
198 m_remaining -= m_block->m_blockSize;
199 m_index -= m_block->m_blockSize;
200 m_total += m_block->m_blockSize;
201 m_block = m_block->m_next;
207 #ifdef DACCESS_COMPILE
210 ArrayListBase::EnumMemoryRegions(CLRDataEnumMemoryFlags flags)
214 // Assume that 'this' is enumerated, either explicitly
215 // or because this class is embedded in another.
217 PTR_ArrayListBlock block = m_firstBlock.m_next;
218 while (block.IsValid())
221 block = block->m_next;
225 #endif // #ifdef DACCESS_COMPILE