public int Free(PoolAllocItem allocItem) { bool lockAcquired = false; try { if (null != allocItem) { lockAcquired = Monitor.TryEnter(this); if (lockAcquired) { if (allocItem == _listOfAllocItems[0]) { Debug.Assert(allocItem.StartIndex._blockIndex == _reclaimIndex._blockIndex && allocItem.StartIndex._blockOffset == _reclaimIndex._blockOffset); _reclaimIndex._blockIndex = allocItem.EndIndex._blockIndex; _reclaimIndex._blockOffset = allocItem.EndIndex._blockOffset; _listOfAllocItems.RemoveAt(0); _freeSize += (int)(allocItem.Length); _itemPool.Enqueue(allocItem); Debug.Assert(_freeSize >= 0 && _freeSize <= _totalSize); } else if (allocItem == _listOfAllocItems[_listOfAllocItems.Count - 1]) { _listOfAllocItems.RemoveAt(_listOfAllocItems.Count - 1); _allocIndex._blockIndex = allocItem.StartIndex._blockIndex; _allocIndex._blockOffset = allocItem.StartIndex._blockOffset; _freeSize += (int)(allocItem.Length); _itemPool.Enqueue(allocItem); if (_listOfAllocItems.Count > 0) { Debug.Assert(_listOfAllocItems[_listOfAllocItems.Count - 1].EndIndex._blockIndex == _allocIndex._blockIndex && _listOfAllocItems[_listOfAllocItems.Count - 1].EndIndex._blockOffset == _allocIndex._blockOffset); } } else { Debugger.Break(); throw new System.NotSupportedException("FIFOMemoryPool only supports first alloc first reclaim, or reclaim most recent allocation"); } _freeCount++; _allocatedCount--; if (_freeSize > _shrinkThresholdPercentage * _totalSize && _totalSize > _initialSize) { int blocksToShrink = 0; if (_freeSize == _totalSize) { blocksToShrink = Math.Min(_blockCount / 2, (_blockCount - _allocIndex._blockIndex - 1) / 2); blocksToShrink = Math.Min(blocksToShrink, (_totalSize - _initialSize) / _blockSize); } else if (_allocIndex._blockIndex > _reclaimIndex._blockIndex) { blocksToShrink = (_blockCount - _allocIndex._blockIndex - 1) / 2; blocksToShrink = Math.Min(blocksToShrink, (_totalSize - _initialSize) / _blockSize); } if (blocksToShrink > 0) { HLSTrace.WriteLine("Try to shrink pool"); double shrinkRatio = (double)blocksToShrink / _blockCount; int itemPoolToShrink = (int)(_itemPool.Count * shrinkRatio); while (itemPoolToShrink > 0) { _itemPool.Dequeue(); itemPoolToShrink--; } _blockCount -= blocksToShrink; _freeSize -= blocksToShrink * _blockSize; _totalSize -= blocksToShrink * _blockSize; _listOfBlocks.RemoveRange(_listOfBlocks.Count - blocksToShrink, blocksToShrink); _shrinkCount++; } } return 0; } else { return -1; } } else { return 0; } } finally { if (lockAcquired) { Monitor.Exit(this); } } }
public int GrowAlloc(PoolAllocItem allocItem, int growSize) { bool lockAcquired = false; try { lockAcquired = Monitor.TryEnter(this); if (lockAcquired) { if (_allocIndex._blockIndex == allocItem.EndIndex._blockIndex && _allocIndex._blockOffset == allocItem.EndIndex._blockOffset) { while (_freeSize < growSize) { GrowPool(); } int absoluteAllocOffset = _allocIndex._blockIndex * _blockSize + _allocIndex._blockOffset; int newAbsoluteAllocOffset = (absoluteAllocOffset + growSize) % _totalSize; int index = newAbsoluteAllocOffset / _blockSize; int offset = newAbsoluteAllocOffset % _blockSize; _allocIndex._blockIndex = index; _allocIndex._blockOffset = offset; allocItem.EndIndex._blockIndex = index; allocItem.EndIndex._blockOffset = offset; _freeSize -= growSize; Debug.Assert(_freeSize >= 0 && _freeSize <= _totalSize); _accumulatedAllocSize += growSize; _allocCount++; } else { throw new System.NotSupportedException("FIFOMemoryPool only supports grow most recent allocation!"); } return growSize; } else { return -1; } } finally { if (lockAcquired) { Monitor.Exit(this); } } }
public PoolAllocItem Alloc(int size) { lock (this) { while (_freeSize < size) { GrowPool(); } int absoluteAllocOffset = _allocIndex._blockIndex * _blockSize + _allocIndex._blockOffset; int newAbsoluteAllocOffset = (absoluteAllocOffset + size) % _totalSize; int index = newAbsoluteAllocOffset / _blockSize; int offset = newAbsoluteAllocOffset % _blockSize; PoolAllocItem allocItem = null; if (_itemPool.Count == 0) { allocItem = new PoolAllocItem(new PoolBlockIndex(_allocIndex), new PoolBlockIndex(index, offset), this); } else { allocItem = _itemPool.Dequeue(); allocItem.Reset(this); allocItem.StartIndex._blockIndex = _allocIndex._blockIndex; allocItem.StartIndex._blockOffset = _allocIndex._blockOffset; allocItem.EndIndex._blockIndex = index; allocItem.EndIndex._blockOffset = offset; } _allocIndex._blockIndex = index; _allocIndex._blockOffset = offset; _listOfAllocItems.Add(allocItem); _freeSize -= size; _allocCount++; _accumulatedAllocSize += size; _allocatedCount++; Debug.Assert(_freeSize >= 0 && _freeSize <= _totalSize); return allocItem; } }