//#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>(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(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 Allocate() { if (m_freeBlocks.Count == 0) { if (m_extendAble) { m_freeBlocks.Add(new List(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 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> 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 DefaultSettings = new Dictionary(); 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 m_bPool = new Dictionary(); public List Allocate(int capacity) { #if PATH2DPOOL_DISABLE return new List( 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 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> m_allocated = new HashSet>(); #endif } }