Пример #1
0
 public MemTree(int blocks)
 {
     root = new ContentNode()
     {
         FirstBlock = 0, LastBlock = blocks - 1
     };
 }
Пример #2
0
        // 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);
        }
Пример #3
0
        // removes the rightmost leaf from the tree
        public override IMemTreeNode SnipRightLeaf()
        {
            IMemTreeNode newRightChild = rightChild.SnipRightLeaf();

            if (newRightChild == null)
            {   // rightChild is a leaf node
                return(leftChild);
            }
            else
            {
                rightChild       = newRightChild;
                contiguousBlocks = (leftChild.ContiguousBlocks < rightChild.ContiguousBlocks) ? rightChild.ContiguousBlocks : leftChild.ContiguousBlocks;
                return(this);
            }
        }
Пример #4
0
 // frees the specified number of blocks at the given offset
 public void Free(int offset, int blocks)
 {
     // walk the tree, locating the node that holds the blocks to be freed
     if (root == null)
     {
         root = new ContentNode()
         {
             FirstBlock = offset, LastBlock = offset + blocks - 1
         };
     }
     else
     {
         root = root.Free(offset, blocks);
     }
 }
Пример #5
0
 private IMemTreeNode Merge()
 {
     if (rightChild is ContentNode)
     {
         if (leftChild is ContentNode)
         {
             // if they're both contentnodes, we can just substitute them with a single new contentnode
             return(new ContentNode()
             {
                 FirstBlock = leftChild.FirstBlock, LastBlock = rightChild.LastBlock
             });
         }
         else
         {   // right is a contentnode, but left isn't
             // merge the right contentnode into the lefttree
             leftChild.ExpandRightLeaf(rightChild.LastBlock - leftChild.RightLeaf.LastBlock);
             return(leftChild);
         }
     }
     else if (leftChild is ContentNode)
     {   // left is a contentnode, but right isn't
         // merge the left contentnode into the righttree
         rightChild.ExpandLeftLeaf(rightChild.LeftLeaf.FirstBlock - leftChild.FirstBlock);
         return(rightChild);
     }
     else
     {   // both left and right are index nodes. f**k it.
         // snip the leftmost leaf off the right tree
         IMemTreeNode snipped = rightChild.LeftLeaf;
         rightChild = rightChild.SnipLeftLeaf();
         // append that to the rightmost leaf of the left tree
         leftChild.RightLeaf.LastBlock = snipped.LastBlock;
         contiguousBlocks = (leftChild.ContiguousBlocks < rightChild.ContiguousBlocks) ? rightChild.ContiguousBlocks : leftChild.ContiguousBlocks;
         return(this);
     }
 }
Пример #6
0
        public override IMemTreeNode Free(int offset, int blocks)
        {
            if (leftChild.LastBlock > offset) // is this offset contained in the left subtree?
            {
                leftChild        = leftChild.Free(offset, blocks);
                contiguousBlocks = (leftChild.ContiguousBlocks < rightChild.ContiguousBlocks) ? rightChild.ContiguousBlocks : leftChild.ContiguousBlocks;

                if (leftChild.LastBlock + 1 == rightChild.FirstBlock)
                {   // left and right nodes have become contiguous, so merge them
                    return(Merge());
                }

                return(this);
            }
            else if (rightChild.FirstBlock < offset) //is this offset contained in the right subtree?
            {
                rightChild       = rightChild.Free(offset, blocks);
                contiguousBlocks = (leftChild.ContiguousBlocks < rightChild.ContiguousBlocks) ? rightChild.ContiguousBlocks : leftChild.ContiguousBlocks;

                if (leftChild.LastBlock + 1 == rightChild.FirstBlock)
                {   // left and right nodes have become contiguous, so merge them
                    return(Merge());
                }

                return(this);
            }
            else
            {
                // oh crap, not in either of them. Guess we'll have to handle this ourselves.
                // does the block to free lie adjacent ot the leftchild or rightchild?
                bool leftAdjacent, rightAdjacent;
                leftAdjacent  = (offset - 1 == leftChild.LastBlock);
                rightAdjacent = (offset + blocks == rightChild.FirstBlock);

                if (leftAdjacent)
                {
                    if (rightAdjacent)
                    {   // Adjacent to both right and left, so merge them into one.
                        return(Merge());
                    }
                    else
                    {   // Adjacent to left only, expand left
                        leftChild.ExpandRightLeaf(blocks);
                        contiguousBlocks = (leftChild.ContiguousBlocks < rightChild.ContiguousBlocks) ? rightChild.ContiguousBlocks : leftChild.ContiguousBlocks;
                        return(this);
                    }
                }
                else if (rightAdjacent)
                {   // adjacent to right only, expand right;
                    rightChild.ExpandLeftLeaf(blocks);
                    contiguousBlocks = (leftChild.ContiguousBlocks < rightChild.ContiguousBlocks) ? rightChild.ContiguousBlocks : leftChild.ContiguousBlocks;
                    return(this);
                }
                else
                {
                    // adjacent to nothing, create new contentnode for the freed space, and a new index node to contain it.
                    ContentNode newContentNode = new ContentNode()
                    {
                        FirstBlock = offset, LastBlock = offset + blocks - 1
                    };
                    IndexNode newIndexNode = null;
                    if (IMemTreeNode.MergeDirection)
                    {
                        newIndexNode = new IndexNode(newContentNode, rightChild); // merging it into right subtree
                        return(new IndexNode(leftChild, newIndexNode));
                    }
                    else
                    {
                        newIndexNode = new IndexNode(leftChild, newContentNode); // merging it into left subtree
                        return(new IndexNode(newIndexNode, rightChild));
                    }
                }
            }
        }
Пример #7
0
        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;
            //}
        }
Пример #8
0
 public IndexNode(IMemTreeNode left, IMemTreeNode right)
 {
     leftChild        = left;
     rightChild       = right;
     contiguousBlocks = (left.ContiguousBlocks < right.ContiguousBlocks) ? right.ContiguousBlocks : left.ContiguousBlocks;
 }