176 lines
4.7 KiB
C#
176 lines
4.7 KiB
C#
|
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<int, Settings> _defaultSettings = new Dictionary<int, Settings>();
|
|||
|
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<int, BlockAllocator> _bPool = new Dictionary<int, BlockAllocator>();
|
|||
|
|
|||
|
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();
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
}
|