/// <summary> /// Allocate a block of memory based upon a best fit policy. /// </summary> /// <param name="iBlockSizeRequest"></param> /// <returns></returns> public MemoryBlock Allocate(int iBlockSizeRequest) { try { IEnumerable <KeyValuePair <int, List <int> > > availableMemoryBlocks = from entry in MemoryPool where (entry.Key) >= iBlockSizeRequest orderby entry.Key ascending select entry; if (0 == availableMemoryBlocks.Count()) { return(new MemoryBlock()); } KeyValuePair <int, List <int> > smallestBlocks = availableMemoryBlocks.First(); int iBlockSize = smallestBlocks.Key; int iBlockAddress = smallestBlocks.Value.First(); smallestBlocks.Value.RemoveAt(0); if (0 == smallestBlocks.Value.Count()) { MemoryPool.Remove(iBlockSize); } if (iBlockSize > iBlockSizeRequest) { int iBlockRemainderSize = iBlockSize - iBlockSizeRequest; int iBlockRemainderAddress = iBlockAddress + iBlockSizeRequest; if (MemoryPool.ContainsKey(iBlockRemainderSize)) { Debug.Assert(!MemoryPool[iBlockRemainderSize].Contains(iBlockRemainderAddress)); MemoryPool[iBlockRemainderSize].Add(iBlockRemainderAddress); } else { MemoryPool.Add(iBlockRemainderSize, new List <int>() { iBlockRemainderAddress }); } } return(new MemoryBlock() { BlockAddress = iBlockAddress, BlockSize = iBlockSizeRequest }); } catch (Exception) { throw; } }
/// <summary> /// Free memory back into memory buffer. /// </summary> /// <param name="m"></param> public void Free(MemoryBlock m) { if (null == m || m.IsNull()) { return; } try { int iBlockAddressStart = m.BlockAddress; int iBlockAddressEnd = m.BlockAddress + m.BlockSize; int iMergeBlockSize = m.BlockSize; int iMergeBlockAddress = m.BlockAddress; // If Block Address is already available, then ignore foreach (KeyValuePair <int, List <int> > kvp in MemoryPool) { if (kvp.Value.Contains(m.BlockAddress)) { return; } } // Merge with existing block with start of address bool fMergeStart = false; int iMergeStartBlockSize = 0; int iMergeStartBlockAddress = 0; foreach (KeyValuePair <int, List <int> > kvp in MemoryPool) { int iBlockSize = kvp.Key; foreach (int iBlockAddress in kvp.Value) { if (iBlockAddress > iBlockAddressStart) { continue; } if (iBlockSize + iBlockAddress == iBlockAddressStart) { fMergeStart = true; iMergeStartBlockSize = iBlockSize; iMergeStartBlockAddress = iBlockAddress; MemoryPool[iBlockSize].Remove(iBlockAddress); if (0 == MemoryPool[iBlockSize].Count()) { MemoryPool.Remove(iBlockSize); } break; } } if (fMergeStart) { break; } } // Merge existing block with the end of the block if (fMergeStart) { iMergeBlockSize += iMergeStartBlockSize; iMergeBlockAddress = iMergeStartBlockAddress; } bool fMergeEnd = false; int iMergeEndBlockSize = 0; int iMergeEndBlockAddress = 0; IEnumerable <KeyValuePair <int, List <int> > > availableMemoryBlocksWithAddressEnd = from entry in MemoryPool where (entry.Value.Contains(iBlockAddressEnd)) select entry; if (0 < availableMemoryBlocksWithAddressEnd.Count()) { fMergeEnd = true; KeyValuePair <int, List <int> > kvp = availableMemoryBlocksWithAddressEnd.First(); iMergeEndBlockSize = kvp.Key; iMergeEndBlockAddress = iBlockAddressEnd; Debug.Assert(MemoryPool[iMergeEndBlockSize].Contains(iMergeEndBlockAddress)); MemoryPool[iMergeEndBlockSize].Remove(iMergeEndBlockAddress); if (0 == MemoryPool[iMergeEndBlockSize].Count) { MemoryPool.Remove(iMergeEndBlockSize); } } if (fMergeEnd) { iMergeBlockSize += iMergeEndBlockSize; } if (MemoryPool.Keys.Contains(iMergeBlockSize)) { MemoryPool[iMergeBlockSize].Add(iMergeBlockAddress); } else { MemoryPool.Add(iMergeBlockSize, new List <int>() { iMergeBlockAddress }); } } catch (Exception) { throw; } }