private void Expand() { if (this._freePageList._head == -1) { int length; if (this._pages == null) { length = 0; } else { length = this._pages.Length; } int num2 = length * 2; UsagePage[] pageArray = new UsagePage[Math.Min(Math.Max(length + 10, num2), length + 340)]; for (int j = 0; j < length; j++) { pageArray[j] = this._pages[j]; } for (int k = length; k < pageArray.Length; k++) { pageArray[k]._pagePrev = k - 1; pageArray[k]._pageNext = k + 1; } pageArray[length]._pagePrev = -1; pageArray[pageArray.Length - 1]._pageNext = -1; this._freePageList._head = length; this._freePageList._tail = pageArray.Length - 1; this._pages = pageArray; } int pageIndex = this.RemoveFromListHead(ref this._freePageList); this.AddToListHead(pageIndex, ref this._freeEntryList); UsageEntry[] entryArray = new UsageEntry[0x80]; entryArray[0]._cFree = 0x7f; for (int i = 0; i < (entryArray.Length - 1); i++) { entryArray[i]._ref1._next = new UsageEntryRef(pageIndex, i + 1); } entryArray[entryArray.Length - 1]._ref1._next = UsageEntryRef.INVALID; this._pages[pageIndex]._entries = entryArray; this._cPagesInUse++; this.UpdateMinEntries(); }
void ExpandEntries() { Debug.Assert(_freeHead == -1, "_freeHead == -1"); Debug.Assert(_freeTail == -1, "_freeTail == -1"); Debug.Assert(_cFree == 0, "_cFree == 0"); Debug.Assert(_cFreeLast == 0, "_cFreeLast == 0"); // allocate new array int oldSize = _entries.Length; int newSize = Math.Max(oldSize * 2, MIN_ENTRIES); UsageEntry[] entries = new UsageEntry[newSize]; // copy old contents int i; for (i = 0; i < oldSize; i++) { entries[i] = _entries[i]; } // init free list int c = newSize - oldSize - 1; while (c-- > 0) { entries[i].ref1.next = i + 1; i++; } entries[i].ref1.next = -1; _freeHead = oldSize; _freeTail = i; // replace _cFreeLast = newSize / 2; _cFree = newSize - oldSize; _entries = entries; Debug.Trace("CacheUsageExpand", "Expanded from " + oldSize + " to newSize"); }
private void Expand() { if (this._freePageList._head == -1) { int length; if (this._pages == null) { length = 0; } else { length = this._pages.Length; } int num2 = length * 2; UsagePage[] pageArray = new UsagePage[Math.Min(Math.Max(length + 10, num2), length + 340)]; for (int j = 0; j < length; j++) { pageArray[j] = this._pages[j]; } for (int k = length; k < pageArray.Length; k++) { pageArray[k]._pagePrev = k - 1; pageArray[k]._pageNext = k + 1; } pageArray[length]._pagePrev = -1; pageArray[pageArray.Length - 1]._pageNext = -1; this._freePageList._head = length; this._freePageList._tail = pageArray.Length - 1; this._pages = pageArray; } int pageIndex = this.RemoveFromListHead(ref this._freePageList); this.AddToListHead(pageIndex, ref this._freeEntryList); UsageEntry[] entryArray = new UsageEntry[0x80]; entryArray[0]._cFree = 0x7f; for (int i = 0; i < (entryArray.Length - 1); i++) { entryArray[i]._ref1._next = new UsageEntryRef(pageIndex, i + 1); } entryArray[entryArray.Length - 1]._ref1._next = UsageEntryRef.INVALID; this._pages[pageIndex]._entries = entryArray; this._cPagesInUse++; this.UpdateMinEntries(); }
void RemoveEntryAtIndex(CacheEntry cacheEntry, int index) { int prev, next; int length = _entries.Length; int lengthdiv2 = length / 2; Debug.Assert(cacheEntry == _entries[index].cacheEntry, "cacheEntry == _entries[index].cacheEntry"); Debug.Assert((lengthdiv2 & 0x1) == 0, "(lengthdiv2 & 0x1) == 0"); Debug.Assert(index > 0); // update the cache entry cacheEntry.UsageIndex = -1; // update fields Debug.Assert(_entries[index].utcDate != DateTime.MinValue, "_entries[index].utcDate != DateTime.MinValue"); _cInUse--; _entries[index].utcDate = DateTime.MinValue; _entries[index].cacheEntry = null; // remove ref1 from list prev = _entries[index].ref1.prev; next = _entries[index].ref1.next; if (prev >= 0) { Debug.Assert(_entries[prev].ref1.next == index, "_entries[prev].ref1.next == index"); _entries[prev].ref1.next = next; } else { Debug.Assert(_entries[-prev].ref2.next == index, "_entries[-prev].ref2.next == index"); _entries[-prev].ref2.next = next; } if (next >= 0) { Debug.Assert(_entries[next].ref1.prev == index, "_entries[next].ref1.prev == index"); _entries[next].ref1.prev = prev; } else { Debug.Assert(_entries[-next].ref2.prev == index, "_entries[-next].ref2.prev"); _entries[-next].ref2.prev = prev; } // remove ref2 from list prev = _entries[index].ref2.prev; next = _entries[index].ref2.next; if (prev >= 0) { Debug.Assert(_entries[prev].ref1.next == -index, "_entries[prev].ref1.next == -index"); _entries[prev].ref1.next = next; } else { Debug.Assert(_entries[-prev].ref2.next == -index, "_entries[-prev].ref2.next == -index"); _entries[-prev].ref2.next = next; } if (next >= 0) { Debug.Assert(_entries[next].ref1.prev == -index, "_entries[next].ref1.prev == -index"); _entries[next].ref1.prev = prev; } else { Debug.Assert(_entries[-next].ref2.prev == -index, "_entries[-next].ref2.prev == -index"); _entries[-next].ref2.prev = prev; } Debug.Assert(_freeHead == -1 || (_entries[_freeHead].cacheEntry == null && _entries[_freeHead].utcDate == DateTime.MinValue), "_freeHead == -1 || (_entries[_freeHead].cacheEntry == null && _entries[_freeHead].utcDate == DateTime.MinValue)"); Debug.Assert(_freeTail == -1 || (_entries[_freeTail].cacheEntry == null && _entries[_freeTail].utcDate == DateTime.MinValue), "_freeTail == -1 || (_entries[_freeTail].cacheEntry == null && _entries[_freeTail].utcDate == DateTime.MinValue)"); Debug.Assert(_entries[index].cacheEntry == null && _entries[index].utcDate == DateTime.MinValue, "_entries[index].cacheEntry == null && _entries[index].utcDate == DateTime.MinValue"); // add index to free list // if entry is in first half, add to head, else add to tail if (_freeHead == -1) { Debug.Assert(_freeTail == -1, "_freeTail == -1"); _freeHead = _freeTail = index; _entries[index].ref1.next = -1; } else if (index < lengthdiv2) { Debug.Assert(_freeTail != -1, "_freeTail != -1"); _entries[index].ref1.next = _freeHead; _freeHead = index; } else { Debug.Assert(_freeTail != -1, "_freeTail != -1"); Debug.Assert(_entries[_freeTail].ref1.next == -1, "_entries[_freeTail].ref1.next == -1"); _entries[_freeTail].ref1.next = index; _entries[index].ref1.next = -1; _freeTail = index; } _cFree++; if (index >= lengthdiv2) { _cFreeLast++; } // check whether we should realloc _entries // only realloc if 2nd half is empty Debug.Assert(_cFreeLast <= lengthdiv2); if (_cFreeLast == lengthdiv2 && _cInUse * 2 <= lengthdiv2 && MIN_ENTRIES <= lengthdiv2) { int newSize = lengthdiv2; Debug.Assert(_freeHead >= 0 && _freeHead < newSize, "_freeHead >= 0 && _freeHead < newSize"); // alloc and copy to new array UsageEntry[] entries = new UsageEntry[newSize]; _freeHead = -1; _freeTail = -1; _cFree = 0; // copy the two halves, and count _cFreeLast during the second half // don't count entry at index 0 as free entries[0] = _entries[0]; int i = 1, c = 0; for (int halves = 1; halves <= 2; halves++) { _cFreeLast = 0; c += newSize / 2; for (; i < c; i++) { entries[i] = _entries[i]; if (entries[i].utcDate == DateTime.MinValue) { _cFree++; _cFreeLast++; // update free list if (_freeHead == -1) { _freeHead = i; } else { entries[_freeTail].ref1.next = i; } _freeTail = i; } } } Debug.Assert(_freeHead != -1, "_freeHead should not be -1"); Debug.Assert(_freeTail != -1, "_freeTail should not be -1"); // terminate free list entries[_freeTail].ref1.next = -1; //#if DBG // for (; i < length; i++) { // Debug.Assert(_entries[i].utcDate == 0, "_entries[i].utcDate == 0"); // } //#endif _entries = entries; Debug.Trace("CacheUsageContract", "Contracted from " + length + " to newSize"); } }