/// <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; }