// returns the block at which the specifed number of blocks have been allocated // returns -1 if blocks could not be allocated public int Allocate(int blocks) { // Walk down the tree, stopping at the first node that can allocate the needed number of blocks int offset = -1; if (root != null) { root = root.Allocate(blocks, out offset); } return(offset); }
public override IMemTreeNode Allocate(int blocks, out int offset) { // locate a child node that can allocate blocks int leftDelta, rightDelta; leftDelta = leftChild.ContiguousBlocks - blocks; rightDelta = rightChild.ContiguousBlocks - blocks; if (leftDelta < 0 && rightDelta < 0) { offset = -1; return(this); } if (leftDelta < 0) { // left delta is negative, so make sure it loses out in the next if statement leftDelta = rightDelta + 1; } else if (rightDelta < 0) { // right delta is negative, so make sure it loses out in the next if statement rightDelta = leftDelta + 1; } // check which side has a contiguous block closest to the size we need if (leftDelta < rightDelta) { // note that this CAN'T fail and return -1; We've just checked that there IS a contiguous block that will hold the allocation leftChild = leftChild.Allocate(blocks, out offset); if (leftChild == null) { // left child was consumed by allocation return(rightChild); } else { // This index nodes will continue to exist, so update the contiguous block count // THIS can be optimized. Taking into account that we know the contiguous count for the subnodes before the allocation, and how many blocks we'll be shaving off // it is possible to determine wether we actually need to do this update or not. contiguousBlocks = (leftChild.ContiguousBlocks < rightChild.ContiguousBlocks) ? rightChild.ContiguousBlocks : leftChild.ContiguousBlocks; return(this); } } else { // note that this CAN'T fail and return -1; We've just checked that there IS a contiguous block that will hold the allocation rightChild = rightChild.Allocate(blocks, out offset); if (rightChild == null) { // right child was consumed by allocation return(leftChild); } else { // This index nodes will continue to exist, so update the contiguous block count // THIS can be optimized. Taking into account that we know the contiguous count for the subnodes before the allocation, and how many blocks we'll be shaving off // it is possible to determine wether we actually need to do this update or not. contiguousBlocks = (leftChild.ContiguousBlocks < rightChild.ContiguousBlocks) ? rightChild.ContiguousBlocks : leftChild.ContiguousBlocks; return(this); } } //leftChild = leftChild.Allocate(blocks, out offset); //if (offset == -1) //{ // rightChild = rightChild.Allocate(blocks, out offset); // if (rightChild == null) // { // right child was consumed by allocation // return leftChild; // } // else // { // // This index nodes will continue to exist, so update the contiguous block count // // THIS can be optimized. Taking into account that we know the contiguous count for the subnodes before the allocation, and how many blocks we'll be shaving off // // it is possible to determine wether we actually need to do this update or not. // contiguousBlocks = (contiguousBlocks < rightChild.ContiguousBlocks) ? rightChild.ContiguousBlocks : contiguousBlocks; // return this; // } //} //else if (leftChild == null) //{ // left child was consumed by allocation // return rightChild; //} //else //{ // // This index nodes will continue to exist, so update the contiguous block count // // THIS can be optimized. Taking into account that we know the contiguous count for the subnodes before the allocation, and how many blocks we'll be shaving off // // it is possible to determine wether we actually need to do this update or not. // contiguousBlocks = (leftChild.ContiguousBlocks < contiguousBlocks) ? contiguousBlocks : leftChild.ContiguousBlocks; // return this; //} }