Files
Main/Assets/Plugins/Code/UniScene/PathGrid/Define/Path2dPool.cs
2025-01-25 04:38:09 +08:00

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