296 lines
7.5 KiB
C#
296 lines
7.5 KiB
C#
|
//#define PATH2DPOOL_DISABLE
|
|||
|
//#define PATH2DPOOL_DEBUG
|
|||
|
using System;
|
|||
|
using System.Collections.Generic;
|
|||
|
using UnityEngine;
|
|||
|
|
|||
|
namespace Thousandto.Plugins.PathGrid
|
|||
|
{
|
|||
|
public class Path2dSubPool
|
|||
|
{
|
|||
|
|
|||
|
const int DefaultMaxPathLenNum = 10;
|
|||
|
|
|||
|
public delegate void SweepAction();
|
|||
|
public SweepAction sweeper
|
|||
|
{
|
|||
|
get;
|
|||
|
set;
|
|||
|
}
|
|||
|
public bool extendAble
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
return extendAble;
|
|||
|
}
|
|||
|
set
|
|||
|
{
|
|||
|
extendAble = value;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public void TrimExcess()
|
|||
|
{
|
|||
|
if (m_freeBlocks.Count > m_initMaxPathNum)
|
|||
|
{
|
|||
|
m_freeBlocks.RemoveRange(m_initMaxPathNum, m_freeBlocks.Count - m_initMaxPathNum);
|
|||
|
m_freeBlocks.TrimExcess();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public void Sweep()
|
|||
|
{
|
|||
|
if (sweeper == null)
|
|||
|
{
|
|||
|
TrimExcess();
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
sweeper();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public Path2dSubPool(int pathLength, int maxNum, bool extendAble)
|
|||
|
{
|
|||
|
if (pathLength <= 0)
|
|||
|
{
|
|||
|
pathLength = DefaultMaxPathLenNum;
|
|||
|
}
|
|||
|
m_freeBlocks = new List<List<Vector2>>(maxNum);
|
|||
|
m_maxPathNum = m_freeBlocks.Capacity;
|
|||
|
m_initMaxPathNum = m_maxPathNum;
|
|||
|
m_extendAble = extendAble;
|
|||
|
m_pathLength = pathLength;
|
|||
|
for (int i = 0; i < m_maxPathNum; ++i)
|
|||
|
{
|
|||
|
m_freeBlocks.Add(new List<Vector2>(m_pathLength));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public void Clear()
|
|||
|
{
|
|||
|
m_freeBlocks.Clear();
|
|||
|
}
|
|||
|
|
|||
|
public void DeepClear()
|
|||
|
{
|
|||
|
m_freeBlocks.Clear();
|
|||
|
m_freeBlocks.TrimExcess();
|
|||
|
}
|
|||
|
|
|||
|
public int allocatedCount
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
return m_maxPathNum - m_freeBlocks.Count;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public int freeCount
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
return m_freeBlocks.Count;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public List<Vector2> Allocate()
|
|||
|
{
|
|||
|
if (m_freeBlocks.Count == 0)
|
|||
|
{
|
|||
|
if (m_extendAble)
|
|||
|
{
|
|||
|
m_freeBlocks.Add(new List<Vector2>(m_pathLength));
|
|||
|
m_maxPathNum = m_freeBlocks.Capacity;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
return null;
|
|||
|
}
|
|||
|
}
|
|||
|
var last = m_freeBlocks.Count - 1;
|
|||
|
var ret = m_freeBlocks[last];
|
|||
|
m_freeBlocks.RemoveAt(last);
|
|||
|
return ret;
|
|||
|
}
|
|||
|
|
|||
|
public void Free(ref List<Vector2> p)
|
|||
|
{
|
|||
|
if (p.Capacity == m_pathLength)
|
|||
|
{
|
|||
|
p.Clear();
|
|||
|
m_freeBlocks.Add(p);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public int GetTotalSize()
|
|||
|
{
|
|||
|
return m_freeBlocks.Capacity * m_pathLength * 8; // sizeof( Vector2 )
|
|||
|
}
|
|||
|
|
|||
|
int m_maxPathNum = 0;
|
|||
|
int m_pathLength = 0;
|
|||
|
bool m_extendAble = false;
|
|||
|
int m_initMaxPathNum = 0;
|
|||
|
List<List<Vector2>> m_freeBlocks = null;
|
|||
|
}
|
|||
|
|
|||
|
public class Path2dPool
|
|||
|
{
|
|||
|
|
|||
|
public class Settings
|
|||
|
{
|
|||
|
public int pathLength;
|
|||
|
public int maxPathNum;
|
|||
|
public bool extendAble;
|
|||
|
public Settings(int s, int n, bool e)
|
|||
|
{
|
|||
|
pathLength = s;
|
|||
|
maxPathNum = n;
|
|||
|
extendAble = e;
|
|||
|
}
|
|||
|
}
|
|||
|
static Path2dPool m_sharedInstance = null;
|
|||
|
static Dictionary<int, Settings> DefaultSettings = new Dictionary<int, Settings>();
|
|||
|
static Path2dPool()
|
|||
|
{
|
|||
|
DefaultSettings.Add(1 << 1, new Settings(1 << 1, 32, true)); // 4
|
|||
|
DefaultSettings.Add(1 << 2, new Settings(1 << 2, 32, true)); // 4
|
|||
|
DefaultSettings.Add(1 << 3, new Settings(1 << 3, 8, true)); // 8
|
|||
|
DefaultSettings.Add(1 << 4, new Settings(1 << 4, 8, true)); // 16
|
|||
|
DefaultSettings.Add(1 << 5, new Settings(1 << 5, 4, true)); // 32
|
|||
|
|
|||
|
m_sharedInstance = new Path2dPool();
|
|||
|
}
|
|||
|
|
|||
|
public static Path2dPool sharedInstance
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
return m_sharedInstance;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
Path2dSubPool CreateAllocator(int size)
|
|||
|
{
|
|||
|
size = AlignToBlock(size);
|
|||
|
Settings s = null;
|
|||
|
if (DefaultSettings.TryGetValue(size, out s))
|
|||
|
{
|
|||
|
return new Path2dSubPool(s.pathLength, s.maxPathNum, s.extendAble);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
return new Path2dSubPool(size, 8, true);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public static int AlignToBlock(int capacity)
|
|||
|
{
|
|||
|
if ((capacity & (capacity - 1)) != 0)
|
|||
|
{
|
|||
|
capacity = NextPowerOf2(capacity);
|
|||
|
}
|
|||
|
return capacity;
|
|||
|
}
|
|||
|
|
|||
|
public static int NextPowerOf2(int value)
|
|||
|
{
|
|||
|
int rval = 1;
|
|||
|
while (rval < value)
|
|||
|
{
|
|||
|
rval <<= 1;
|
|||
|
}
|
|||
|
return rval;
|
|||
|
}
|
|||
|
|
|||
|
Dictionary<int, Path2dSubPool> m_bPool = new Dictionary<int, Path2dSubPool>();
|
|||
|
|
|||
|
public List<Vector2> Allocate(int capacity)
|
|||
|
{
|
|||
|
#if PATH2DPOOL_DISABLE
|
|||
|
return new List<Vector2>( capacity );
|
|||
|
#else
|
|||
|
capacity = AlignToBlock(capacity);
|
|||
|
Path2dSubPool allocator = null;
|
|||
|
if (!m_bPool.TryGetValue(capacity, out allocator))
|
|||
|
{
|
|||
|
allocator = CreateAllocator(capacity);
|
|||
|
m_bPool.Add(capacity, allocator);
|
|||
|
}
|
|||
|
var r = allocator.Allocate();
|
|||
|
#if PATH2DPOOL_DEBUG
|
|||
|
m_allocated.Add( r );
|
|||
|
#endif
|
|||
|
return r;
|
|||
|
#endif
|
|||
|
}
|
|||
|
|
|||
|
public void Free(ref List<Vector2> p)
|
|||
|
{
|
|||
|
#if PATH2DPOOL_DISABLE
|
|||
|
#else
|
|||
|
if (p != null)
|
|||
|
{
|
|||
|
#if PATH2DPOOL_DEBUG
|
|||
|
FLogger.DebugAssert( m_allocated.Contains( p ) == true );
|
|||
|
m_allocated.Remove( p );
|
|||
|
#endif
|
|||
|
Path2dSubPool allocator = null;
|
|||
|
if (m_bPool.TryGetValue(p.Capacity, out allocator))
|
|||
|
{
|
|||
|
allocator.Free(ref p);
|
|||
|
}
|
|||
|
p = null;
|
|||
|
}
|
|||
|
#endif
|
|||
|
}
|
|||
|
|
|||
|
public Path2dSubPool TryGet(int capacity)
|
|||
|
{
|
|||
|
capacity = AlignToBlock(capacity);
|
|||
|
Path2dSubPool ba = null;
|
|||
|
m_bPool.TryGetValue(capacity, out ba);
|
|||
|
return ba;
|
|||
|
}
|
|||
|
|
|||
|
public Path2dSubPool AddPool(int capacity, int maxnum, bool extendAble = true)
|
|||
|
{
|
|||
|
capacity = AlignToBlock(capacity);
|
|||
|
Path2dSubPool ba = null;
|
|||
|
if (!m_bPool.TryGetValue(capacity, out ba))
|
|||
|
{
|
|||
|
ba = new Path2dSubPool(capacity, maxnum, extendAble);
|
|||
|
m_bPool.Add(capacity, ba);
|
|||
|
}
|
|||
|
return ba;
|
|||
|
}
|
|||
|
|
|||
|
public int GetTotalSize()
|
|||
|
{
|
|||
|
int size = 0;
|
|||
|
foreach (var t in m_bPool)
|
|||
|
{
|
|||
|
size += t.Value.GetTotalSize();
|
|||
|
}
|
|||
|
return size;
|
|||
|
}
|
|||
|
|
|||
|
public Path2dPool()
|
|||
|
{
|
|||
|
}
|
|||
|
|
|||
|
public void Sweep()
|
|||
|
{
|
|||
|
foreach (var t in m_bPool)
|
|||
|
{
|
|||
|
t.Value.Sweep();
|
|||
|
}
|
|||
|
}
|
|||
|
#if PATH2DPOOL_DEBUG
|
|||
|
HashSet<List<Vector2>> m_allocated = new HashSet<List<Vector2>>();
|
|||
|
#endif
|
|||
|
}
|
|||
|
|
|||
|
}
|