ThomagicRenderer/Runtime/CellLayoutPool.cs

86 lines
3.3 KiB
C#

using System;
using System.Collections.Generic;
using UnityEngine;
namespace Assets.ThoMagic.Renderer
{
internal class CellLayoutPool
{
private static readonly Dictionary<CellLayout, int> _hashLookup = new Dictionary<CellLayout, int>();
private static readonly Dictionary<int, CellLayout> _sharedCells = new Dictionary<int, CellLayout>();
private static readonly Dictionary<int, HashSet<int>> _usageTracker = new Dictionary<int, HashSet<int>>();
public static int Count => CellLayoutPool._sharedCells.Count;
internal static bool Validate() => CellLayoutPool._hashLookup.Count == CellLayoutPool._sharedCells.Count && CellLayoutPool._hashLookup.Count == CellLayoutPool._usageTracker.Count;
public static CellLayout Get(
object owner,
float cellSizeX,
float cellSizeZ,
int cellsX,
int cellsZ,
Bounds bounds)
{
if (owner == null)
throw new ArgumentNullException(nameof(owner));
int hashCode = CellLayoutPool.GetHashCode(cellSizeX, cellSizeZ, cellsX, cellsZ, bounds.min);
CellLayout key;
if (!CellLayoutPool._sharedCells.TryGetValue(hashCode, out key))
{
CellLayoutPool._sharedCells[hashCode] = key = new CellLayout(cellSizeX, cellSizeZ, bounds);
CellLayoutPool._hashLookup[key] = hashCode;
}
CellLayoutPool.IncreaseUsage(hashCode, owner);
return key;
}
public static void Return(object owner, CellLayout layout)
{
if (owner == null)
throw new ArgumentNullException(nameof(owner));
int hash = layout != null ? CellLayoutPool.GetHashCode(layout) : throw new ArgumentNullException(nameof(layout));
if (CellLayoutPool.DecreaseUsage(hash, owner) != 0)
return;
CellLayoutPool.Dispose(hash, layout);
}
private static void Dispose(int hash, CellLayout layout)
{
CellLayoutPool._usageTracker.Remove(hash);
CellLayoutPool._sharedCells.Remove(hash);
CellLayoutPool._hashLookup.Remove(layout);
}
private static int GetHashCode(CellLayout layout) => CellLayoutPool._hashLookup[layout];
private static void IncreaseUsage(int hash, object owner)
{
HashSet<int> intSet;
if (!CellLayoutPool._usageTracker.TryGetValue(hash, out intSet) || intSet == null)
CellLayoutPool._usageTracker[hash] = intSet = new HashSet<int>();
int hashCode = owner.GetHashCode();
if (intSet.Contains(hashCode))
return;
intSet.Add(hashCode);
}
private static int DecreaseUsage(int hash, object owner)
{
HashSet<int> intSet = CellLayoutPool._usageTracker[hash];
intSet.Remove(owner.GetHashCode());
return intSet.Count;
}
private static int GetHashCode(
float cellSizeX,
float cellSizeZ,
int cellsX,
int cellsZ,
Vector3 initialOrigin)
{
return HashCode.Combine<float, float, int, int, Vector3>(cellSizeX, cellSizeZ, cellsX, cellsZ, initialOrigin);
}
}
}