//#define ASTAR_NO_POOLING // Disable pooling for some reason. Maybe for debugging or just for measuring the difference. using System; using System.Collections.Generic; using UnityEngine; namespace PF { /** Pools path objects to reduce load on the garbage collector */ public static class PathPool { static readonly Dictionary > pool = new Dictionary >(); static readonly Dictionary totalCreated = new Dictionary(); /** Adds a path to the pool. * This function should not be used directly. Instead use the Path.Claim and Path.Release functions. */ public static void Pool (Path path) { #if !ASTAR_NO_POOLING lock (pool) { if (((IPathInternals)path).Pooled) { throw new System.ArgumentException("The path is already pooled."); } Stack poolStack; if (!pool.TryGetValue(path.GetType(), out poolStack)) { poolStack = new Stack(); pool[path.GetType()] = poolStack; } ((IPathInternals)path).Pooled = true; ((IPathInternals)path).OnEnterPool(); poolStack.Push(path); } #endif } /** Total created instances of paths of the specified type */ public static int GetTotalCreated (Type type) { int created; if (totalCreated.TryGetValue(type, out created)) { return created; } else { return 0; } } /** Number of pooled instances of a path of the specified type */ public static int GetSize (Type type) { Stack poolStack; if (pool.TryGetValue(type, out poolStack)) { return poolStack.Count; } else { return 0; } } /** Get a path from the pool or create a new one if the pool is empty */ public static T GetPath() where T : Path, new() { #if ASTAR_NO_POOLING T result = new T(); ((IPathInternals)result).Reset(); return result; #else lock (pool) { T result; Stack poolStack; if (pool.TryGetValue(typeof(T), out poolStack) && poolStack.Count > 0) { // Guaranteed to have the correct type result = poolStack.Pop() as T; } else { result = new T(); // Make sure an entry for the path type exists if (!totalCreated.ContainsKey(typeof(T))) { totalCreated[typeof(T)] = 0; } totalCreated[typeof(T)]++; } ((IPathInternals)result).Pooled = false; ((IPathInternals)result).Reset(); return result; } #endif } } /** Pools path objects to reduce load on the garbage collector. * \deprecated Generic version is now obsolete to trade an extremely tiny performance decrease for a large decrease in boilerplate for Path classes */ [System.Obsolete("Generic version is now obsolete to trade an extremely tiny performance decrease for a large decrease in boilerplate for Path classes")] public static class PathPool where T : Path, new() { /** Recycles a path and puts in the pool. * This function should not be used directly. Instead use the Path.Claim and Path.Release functions. */ public static void Recycle (T path) { PathPool.Pool(path); } /** Warms up path, node list and vector list pools. * Makes sure there is at least \a count paths, each with a minimum capacity for paths with length \a length in the pool. * The capacity means that paths shorter or equal to the capacity can be calculated without any large allocations taking place. */ public static void Warmup (int count, int length) { ListPool.Warmup(count, length); ListPool.Warmup(count, length); var tmp = new Path[count]; for (int i = 0; i < count; i++) { tmp[i] = GetPath(); tmp[i].Claim(tmp); } for (int i = 0; i < count; i++) tmp[i].Release(tmp); } public static int GetTotalCreated () { return PathPool.GetTotalCreated(typeof(T)); } public static int GetSize () { return PathPool.GetSize(typeof(T)); } [System.Obsolete("Use PathPool.GetPath instead of PathPool.GetPath")] public static T GetPath () { return PathPool.GetPath(); } } }