#region Copyright & License Information /* * Copyright 2007-2015 The OpenRA Developers (see AUTHORS) * This file is part of OpenRA, which is free software. It is made * available to you under the terms of the GNU General Public License * as published by the Free Software Foundation. For more information, * see COPYING. */ #endregion using System.Collections.Generic; using System.Drawing; using OpenRA.Mods.Common.Traits; namespace OpenRA.Mods.Common.Pathfinder { public interface ICellInfoLayerManager { /// /// Gets a CellLayer of Nodes from the pool /// CellLayer GetFromPool(); /// /// Puts a CellLayer into the pool /// void PutBackIntoPool(CellLayer ci); /// /// Creates (or obtains from the pool) a CellLayer given a map /// CellLayer NewLayer(Map map); } public sealed class CellInfoLayerManager : ICellInfoLayerManager { readonly Queue> cellInfoPool = new Queue>(); readonly object defaultCellInfoLayerSync = new object(); CellLayer defaultCellInfoLayer; static ICellInfoLayerManager instance = new CellInfoLayerManager(); public static ICellInfoLayerManager Instance { get { return instance; } } public static void SetInstance(ICellInfoLayerManager cellInfoLayerManager) { instance = cellInfoLayerManager; } public CellLayer GetFromPool() { lock (cellInfoPool) return cellInfoPool.Dequeue(); } public void PutBackIntoPool(CellLayer ci) { lock (cellInfoPool) cellInfoPool.Enqueue(ci); } public CellLayer NewLayer(Map map) { CellLayer result = null; var mapSize = new Size(map.MapSize.X, map.MapSize.Y); // HACK: Uses a static cache so that double-ended searches (which have two PathSearch instances) // can implicitly share data. The PathFinder should allocate the CellInfo array and pass it // explicitly to the things that need to share it. while (cellInfoPool.Count > 0) { var cellInfo = GetFromPool(); if (cellInfo.Size != mapSize || cellInfo.Shape != map.TileShape) { Log.Write("debug", "Discarding old pooled CellInfo of wrong size."); continue; } result = cellInfo; break; } if (result == null) result = new CellLayer(map); lock (defaultCellInfoLayerSync) { if (defaultCellInfoLayer == null || defaultCellInfoLayer.Size != mapSize || defaultCellInfoLayer.Shape != map.TileShape) { defaultCellInfoLayer = CellLayer.CreateInstance( mpos => new CellInfo(int.MaxValue, int.MaxValue, mpos.ToCPos(map), CellStatus.Unvisited), new Size(map.MapSize.X, map.MapSize.Y), map.TileShape); } result.CopyValuesFrom(defaultCellInfoLayer); } return result; } } }