PathPool.cs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. //#define ASTAR_NO_POOLING // Disable pooling for some reason. Maybe for debugging or just for measuring the difference.
  2. using System;
  3. using System.Collections.Generic;
  4. namespace PF {
  5. /** Pools path objects to reduce load on the garbage collector */
  6. public static class PathPool {
  7. static readonly Dictionary<Type, Stack<Path> > pool = new Dictionary<Type, Stack<Path> >();
  8. static readonly Dictionary<Type, int> totalCreated = new Dictionary<Type, int>();
  9. /** Adds a path to the pool.
  10. * This function should not be used directly. Instead use the Path.Claim and Path.Release functions.
  11. */
  12. public static void Pool (Path path) {
  13. #if !ASTAR_NO_POOLING
  14. lock (pool) {
  15. if (((IPathInternals)path).Pooled) {
  16. throw new System.ArgumentException("The path is already pooled.");
  17. }
  18. Stack<Path> poolStack;
  19. if (!pool.TryGetValue(path.GetType(), out poolStack)) {
  20. poolStack = new Stack<Path>();
  21. pool[path.GetType()] = poolStack;
  22. }
  23. ((IPathInternals)path).Pooled = true;
  24. ((IPathInternals)path).OnEnterPool();
  25. poolStack.Push(path);
  26. }
  27. #endif
  28. }
  29. /** Total created instances of paths of the specified type */
  30. public static int GetTotalCreated (Type type) {
  31. int created;
  32. if (totalCreated.TryGetValue(type, out created)) {
  33. return created;
  34. } else {
  35. return 0;
  36. }
  37. }
  38. /** Number of pooled instances of a path of the specified type */
  39. public static int GetSize (Type type) {
  40. Stack<Path> poolStack;
  41. if (pool.TryGetValue(type, out poolStack)) {
  42. return poolStack.Count;
  43. } else {
  44. return 0;
  45. }
  46. }
  47. /** Get a path from the pool or create a new one if the pool is empty */
  48. public static T GetPath<T>() where T : Path, new() {
  49. #if ASTAR_NO_POOLING
  50. T result = new T();
  51. ((IPathInternals)result).Reset();
  52. return result;
  53. #else
  54. lock (pool) {
  55. T result;
  56. Stack<Path> poolStack;
  57. if (pool.TryGetValue(typeof(T), out poolStack) && poolStack.Count > 0) {
  58. // Guaranteed to have the correct type
  59. result = poolStack.Pop() as T;
  60. } else {
  61. result = new T();
  62. // Make sure an entry for the path type exists
  63. if (!totalCreated.ContainsKey(typeof(T))) {
  64. totalCreated[typeof(T)] = 0;
  65. }
  66. totalCreated[typeof(T)]++;
  67. }
  68. ((IPathInternals)result).Pooled = false;
  69. ((IPathInternals)result).Reset();
  70. return result;
  71. }
  72. #endif
  73. }
  74. }
  75. /** Pools path objects to reduce load on the garbage collector.
  76. * \deprecated Generic version is now obsolete to trade an extremely tiny performance decrease for a large decrease in boilerplate for Path classes
  77. */
  78. [System.Obsolete("Generic version is now obsolete to trade an extremely tiny performance decrease for a large decrease in boilerplate for Path classes")]
  79. public static class PathPool<T> where T : Path, new() {
  80. /** Recycles a path and puts in the pool.
  81. * This function should not be used directly. Instead use the Path.Claim and Path.Release functions.
  82. */
  83. public static void Recycle (T path) {
  84. PathPool.Pool(path);
  85. }
  86. /** Warms up path, node list and vector list pools.
  87. * Makes sure there is at least \a count paths, each with a minimum capacity for paths with length \a length in the pool.
  88. * The capacity means that paths shorter or equal to the capacity can be calculated without any large allocations taking place.
  89. */
  90. public static void Warmup (int count, int length) {
  91. ListPool<GraphNode>.Warmup(count, length);
  92. ListPool<Vector3>.Warmup(count, length);
  93. var tmp = new Path[count];
  94. for (int i = 0; i < count; i++) { tmp[i] = GetPath(); tmp[i].Claim(tmp); }
  95. for (int i = 0; i < count; i++) tmp[i].Release(tmp);
  96. }
  97. public static int GetTotalCreated () {
  98. return PathPool.GetTotalCreated(typeof(T));
  99. }
  100. public static int GetSize () {
  101. return PathPool.GetSize(typeof(T));
  102. }
  103. [System.Obsolete("Use PathPool.GetPath<T> instead of PathPool<T>.GetPath")]
  104. public static T GetPath () {
  105. return PathPool.GetPath<T>();
  106. }
  107. }
  108. }