Represents a defined block in memory
Inheritance: IMemoryBlock
        /// <summary>
        /// Marks an allocated block as unallocated
        /// </summary>
        /// <param name="startLocation">Offset of block in slab</param>
        /// <param name="length">Length of block</param>
        protected void AddFreeBlock(long startLocation, long length)
        {
            SortedDictionary<long, IMemoryBlock> innerList;
            if (!freeBlocksList.TryGetValue(length, out innerList))
            {
                innerList = new SortedDictionary<long, IMemoryBlock>();
                freeBlocksList.Add(length, innerList);
            }

            MemoryBlock newFreeBlock = new MemoryBlock(startLocation, length, this);
            innerList.Add(startLocation, newFreeBlock);
            dictStartLoc.Add(startLocation, newFreeBlock);
            dictEndLoc.Add(startLocation + length - 1, newFreeBlock);
            if (GetLargest() < length)
            {
                SetLargest(length);
            }
        }
        /// <summary>
        /// Attempts to allocate a memory block of length between minLength and maxLength (both inclusive)
        /// </summary>
        /// <param name="minLength">The minimum acceptable length</param>
        /// <param name="maxLength">The maximum acceptable length</param>
        /// <param name="allocatedBlock">Allocated memory block</param>
        /// <returns>Length of allocated block if successful, zero otherwise</returns>
        /// <remarks>This overload is useful when multiple threads are concurrently working on the slab and the caller wants to allocate a block up to a desired size</remarks>
        public long TryAllocate(long minLength, long maxLength, out IMemoryBlock allocatedBlock)
        {
            if (minLength > maxLength) throw new ArgumentException("minLength is greater than maxLength", "minLength");
            if (minLength <= 0) throw new ArgumentOutOfRangeException("minLength must be greater than zero", "minLength");
            if (maxLength <= 0) throw new ArgumentOutOfRangeException("maxLength must be greater than zero", "maxLength");

            allocatedBlock = null;
            lock (sync)
            {
                if (freeBlocksList.Count == 0) return 0;

                long[] keys = new long[freeBlocksList.Count];
                freeBlocksList.Keys.CopyTo(keys, 0);

                //Leave if the largest free block cannot hold minLength
                if (keys[keys.LongLength - 1] < minLength)
                {
                    return 0;
                }

                //search freeBlocksList looking for the smallest available free block than can fit maxLength
                long length = maxLength;
                int index = System.Array.BinarySearch<long>(keys, maxLength);
                if (index < 0)
                {
                    index = ~index;
                    if (index >= keys.Length)
                    {
                        //index is set to the largest free block which can hold minLength
                        index = keys.Length - 1;

                        //length is set to the size of that free block
                        length = keys[index];
                    }
                }

                //Grab the first memoryblock in the freeBlockList innerSortedDictionary
                //There is guanranteed to be at least one in the innerList
                FreeSpace foundBlock = dictStartLoc[freeBlocksList[keys[index]][0]];

                if (foundBlock.Length == length)
                {
                    //Perfect match:

                    //Remove existing free block -- and set Largest if need be
                    RemoveFreeBlock(foundBlock, false);

                    allocatedBlock = new MemoryBlock(foundBlock.Offset, foundBlock.Length, this);
                }
                else
                {
                    //FoundBlock is larger than requested block size

                    //Shrink the existing free memory block by the new allocation
                    ShrinkFreeMemoryBlock(foundBlock, foundBlock.Length - length);

                    allocatedBlock = new MemoryBlock(foundBlock.Offset, length, this);
                }

                return length;
            }
        }
        /// <summary>
        /// Attempts to allocate a memory block of a specified length.
        /// </summary>
        /// <param name="length">Length, in bytes, of memory block</param>
        /// <param name="allocatedBlock">Allocated memory block</param>
        /// <returns>True, if memory block was allocated. False, if otherwise</returns>
        public virtual bool TryAllocate(long length, out IMemoryBlock allocatedBlock)
        {
            allocatedBlock = null;
            lock (sync)
            {
                if (GetLargest() < length) return false;

                //search freeBlocksList looking for the smallest available free block
                long[] keys = new long[freeBlocksList.Count];
                freeBlocksList.Keys.CopyTo(keys, 0);
                int index = System.Array.BinarySearch<long>(keys, length);
                if (index < 0)
                {
                    index = ~index;
                    if (index >= keys.LongLength)
                    {
                        return false;
                    }
                }

                //Grab the first memoryblock in the freeBlockList innerSortedDictionary
                //There is guanranteed to be an innerSortedDictionary with at least 1 key=value pair
                IMemoryBlock foundBlock = null;
                foreach (KeyValuePair<long, IMemoryBlock> kvPair in freeBlocksList[keys[index]])
                {
                    foundBlock = kvPair.Value;
                    break;
                }

                //Remove existing free block
                RemoveFreeBlock(foundBlock);

                if (foundBlock.Length == length)
                {
                    //Perfect match
                    allocatedBlock = foundBlock;
                }
                else
                {
                    //FoundBlock is larger than requested block size

                    allocatedBlock = new MemoryBlock(foundBlock.StartLocation, length, this);

                    long newFreeStartLocation = allocatedBlock.EndLocation + 1;
                    long newFreeSize = foundBlock.Length - length;

                    //add new Freeblock with the smaller remaining space
                    AddFreeBlock(newFreeStartLocation, newFreeSize);

                }

            }

            return true;
        }
 internal virtual IMemoryBlock CreateInvalidMemoryBlock_NullSlab()
 {
     IMemoryBlock target = new MemoryBlock(startLoc, length, null);
     return target;
 }
 internal virtual IMemoryBlock CreateInvalidMemoryBlock_BadLength2()
 {
     IMemoryBlock target = new MemoryBlock(startLoc, 0, slab);
     return target;
 }
 internal virtual IMemoryBlock CreateInvalidIMemoryBlock_BadStartLoc()
 {
     IMemoryBlock target = new MemoryBlock(-1, length, slab);
     return target;
 }
 internal virtual IMemoryBlock CreateIMemoryBlock()
 {
     IMemoryBlock target = new MemoryBlock(startLoc, length, slab);
     return target;
 }