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