using System; using System.Collections.Generic; using System.Text; namespace Thousandto.Core.Base { public class BlockPool : IObjectPool { public class Settings { public int BlockSize; public int MaxBlockNum; public bool ExtendAble; public Settings(int s, int n, bool e) { BlockSize = s; MaxBlockNum = n; ExtendAble = e; } } static BlockPool _sharedInstance = null; static Dictionary _defaultSettings = new Dictionary(); static BlockPool() { _defaultSettings.Add(1 << 2, new Settings(1 << 2, 16, true)); // 4 _defaultSettings.Add(1 << 3, new Settings(1 << 3, 64, true)); // 8 _defaultSettings.Add(1 << 4, new Settings(1 << 4, 64, true)); // 16 _defaultSettings.Add(1 << 5, new Settings(1 << 5, 64, true)); // 32 _defaultSettings.Add(1 << 6, new Settings(1 << 6, 64, true)); // 64 _defaultSettings.Add(1 << 7, new Settings(1 << 7, 32, true)); // 128 _defaultSettings.Add(1 << 8, new Settings(1 << 8, 16, true)); // 256 _sharedInstance = new BlockPool(); } public static BlockPool SharedInstance { get { return _sharedInstance; } } BlockAllocator CreateAllocator(int size) { size = AlignToBlock(size); Settings s = null; if (_defaultSettings.TryGetValue(size, out s)) { return new BlockAllocator(s.BlockSize, s.MaxBlockNum, s.ExtendAble); } else { return new BlockAllocator(size, 8, true); } } public static int AlignToBlock(int size) { size = ((size + 3) & ~3); // 4 bytes aligned if ((size & (size - 1)) != 0) { size = NextPowerOf2(size); } return size; } public static int NextPowerOf2(int value) { int rval = 1; while (rval < value) { rval <<= 1; } return rval; } public static void MemSet(byte[] array, byte value) { if (array == null) { throw new ArgumentNullException("array"); } int block = 32, index = 0; int length = Math.Min(block, array.Length); //Fill the initial array while (index < length) { array[index++] = value; } length = array.Length; while (index < length) { Buffer.BlockCopy(array, 0, array, index, Math.Min(block, length - index)); index += block; block *= 2; } } Dictionary _bPool = new Dictionary(); public byte[] Allocate(int size) { size = AlignToBlock(size); BlockAllocator allocator = null; if (!_bPool.TryGetValue(size, out allocator)) { allocator = CreateAllocator(size); _bPool.Add(size, allocator); } return allocator.Allocate(); } public void Free(ref byte[] p) { if (p != null) { BlockAllocator allocator = null; if (_bPool.TryGetValue(p.Length, out allocator)) { allocator.Free(p); } p = null; } } public BlockAllocator TryGet(int size) { size = AlignToBlock(size); BlockAllocator ba = null; _bPool.TryGetValue(size, out ba); return ba; } public BlockAllocator AddPool(int size, int maxnum, bool extendAble = true) { size = AlignToBlock(size); BlockAllocator ba = null; if (!_bPool.TryGetValue(size, out ba)) { ba = new BlockAllocator(size, maxnum, extendAble); _bPool.Add(size, ba); } return ba; } public int GetTotalSize() { int size = 0; foreach (var t in _bPool) { size += t.Value.GetTotalSize(); } return size; } public BlockPool() { } public void Sweep() { foreach (var t in _bPool) { t.Value.Sweep(); } } } }