private void AddToBinChain(long pointer, long size)
{
CheckOffset(pointer);
// What bin would this area fit into?
int binChainIndex = MinimumBinSizeIndex(size);
var headerInfo = new long[2];
long curOffset = freeBinList[binChainIndex];
if (curOffset == -1) {
// If the bin chain has no elements,
headerInfo[0] = (size | DeletedFlag);
headerInfo[1] = -1;
ReboundArea(pointer, headerInfo, true);
freeBinList[binChainIndex] = pointer;
WriteBinIndex(binChainIndex);
} else {
bool inserted = false;
long lastOffset = -1;
int searches = 0;
while (curOffset != -1 && inserted == false) {
// Get the current offset
ReadAreaHeader(curOffset, headerInfo);
long header = headerInfo[0];
long next = headerInfo[1];
// Assert - the header must have deleted flag
if ((header & DeletedFlag) == 0)
throw new IOException("Area not marked as deleted.");
long areaSize = header ^ DeletedFlag;
if (areaSize >= size || searches >= 12) {
// Insert if the area size is >= than the size we are adding.
// Set the previous header to point to this
long previous = lastOffset;
// Set up the deleted area
headerInfo[0] = (size | DeletedFlag);
headerInfo[1] = curOffset;
ReboundArea(pointer, headerInfo, true);
if (lastOffset != -1) {
// Set the previous input the chain to point to the deleted area
ReadAreaHeader(previous, headerInfo);
headerInfo[1] = pointer;
ReboundArea(previous, headerInfo, false);
} else {
// Otherwise set the head bin item
freeBinList[binChainIndex] = pointer;
WriteBinIndex(binChainIndex);
}
inserted = true;
}
lastOffset = curOffset;
curOffset = next;
++searches;
}
// If we reach the end and we haven't inserted,
if (!inserted) {
// Set the new deleted area.
headerInfo[0] = (size | DeletedFlag);
headerInfo[1] = -1;
ReboundArea(pointer, headerInfo, true);
// Set the previous entry to this
ReadAreaHeader(lastOffset, headerInfo);
headerInfo[1] = pointer;
ReboundArea(lastOffset, headerInfo, false);
}
}
}