Files
OpenRA/OpenRA.Mods.Common/Pathfinder/CellInfoLayerManager.cs
2015-07-22 06:36:00 +02:00

111 lines
2.9 KiB
C#

#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
{
/// <summary>
/// Gets a CellLayer of Nodes from the pool
/// </summary>
CellLayer<CellInfo> GetFromPool();
/// <summary>
/// Puts a CellLayer into the pool
/// </summary>
void PutBackIntoPool(CellLayer<CellInfo> ci);
/// <summary>
/// Creates (or obtains from the pool) a CellLayer given a map
/// </summary>
CellLayer<CellInfo> NewLayer(Map map);
}
public sealed class CellInfoLayerManager : ICellInfoLayerManager
{
readonly Queue<CellLayer<CellInfo>> cellInfoPool = new Queue<CellLayer<CellInfo>>();
readonly object defaultCellInfoLayerSync = new object();
CellLayer<CellInfo> defaultCellInfoLayer;
static ICellInfoLayerManager instance = new CellInfoLayerManager();
public static ICellInfoLayerManager Instance
{
get
{
return instance;
}
}
public static void SetInstance(ICellInfoLayerManager cellInfoLayerManager)
{
instance = cellInfoLayerManager;
}
public CellLayer<CellInfo> GetFromPool()
{
lock (cellInfoPool)
return cellInfoPool.Dequeue();
}
public void PutBackIntoPool(CellLayer<CellInfo> ci)
{
lock (cellInfoPool)
cellInfoPool.Enqueue(ci);
}
public CellLayer<CellInfo> NewLayer(Map map)
{
CellLayer<CellInfo> 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<CellInfo>(map);
lock (defaultCellInfoLayerSync)
{
if (defaultCellInfoLayer == null ||
defaultCellInfoLayer.Size != mapSize ||
defaultCellInfoLayer.Shape != map.TileShape)
{
defaultCellInfoLayer =
CellLayer<CellInfo>.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;
}
}
}