using System; using System.Collections.Generic; using System.Text; namespace Thousandto.Core.Base { public class BlockAllocator { const int DefaultMaxBlockNum = 100; public delegate void SweepAction(); public SweepAction Sweeper { get; set; } public bool ExtendAble { get { return _extendAble; } set { _extendAble = value; } } public void TrimExcess() { if ( _freeBlocks.Count > _initMaxBlockNum ) { _freeBlocks.RemoveRange( _initMaxBlockNum, _freeBlocks.Count - _initMaxBlockNum ); _freeBlocks.TrimExcess(); } } public void Sweep() { if ( Sweeper == null ) { TrimExcess(); } else { Sweeper(); } } public BlockAllocator( int theBlockSize, int maxBlock, bool theExtendAble ) { _blockSize = theBlockSize; if ( maxBlock <= 0 ) { maxBlock = DefaultMaxBlockNum; } _freeBlocks = new List( maxBlock ); _maxBlockNum = _freeBlocks.Capacity; _initMaxBlockNum = _maxBlockNum; _extendAble = theExtendAble; for ( int i = 0; i < _maxBlockNum; ++i ) { _freeBlocks.Add( new byte[_blockSize] ); } } public void Clear() { _freeBlocks.Clear(); } public void DeepClear() { _freeBlocks.Clear(); _freeBlocks.TrimExcess(); } public int AllocatedCount { get { return _maxBlockNum - _freeBlocks.Count; } } public int FreeCount { get { return _freeBlocks.Count; } } public byte[] Allocate() { if ( _freeBlocks.Count == 0 ) { if ( _extendAble ) { _freeBlocks.Add( new byte[_blockSize] ); _maxBlockNum = _freeBlocks.Capacity; } else { return null; } } var last = _freeBlocks.Count - 1; var ret = _freeBlocks[last]; _freeBlocks.RemoveAt( last ); return ret; } public void Free( byte[] p ) { if ( p.Length == _blockSize ) { _freeBlocks.Add( p ); } } public int GetTotalSize() { return _freeBlocks.Capacity * _blockSize; } int _blockSize = 0; int _maxBlockNum = 0; bool _extendAble = false; int _initMaxBlockNum = 0; List _freeBlocks = null; } }