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