Files
FueraDeEscala/Assets/Game Kit Controller/Integrations/LimbHacker-master/Guts/CollectionPool.cs

89 lines
2.4 KiB
C#
Raw Normal View History

2026-03-29 23:03:14 -07:00
using System;
using System.Collections.Generic;
namespace NobleMuffins.LimbHacker.Guts
{
public class CollectionPool<TCollection, TElement> where TCollection: class, ICollection<TElement>
{
private readonly object key = new object ();
private readonly int poolSize;
private readonly TCollection[] poolTable;
private readonly bool[] useTable;
private readonly Func<int, TCollection> instantiateWithCapacity;
private readonly Func<TCollection, int> getCapacity;
public CollectionPool (int poolSize, Func<TCollection, int> getCapacity, Func<int, TCollection> instantiateWithCapacity)
{
this.poolSize = poolSize;
this.getCapacity = getCapacity;
this.instantiateWithCapacity = instantiateWithCapacity;
poolTable = new TCollection[poolSize];
useTable = new bool[poolSize];
}
public DisposableBundle<TCollection> Get (int desiredCapacity)
{
TCollection o = null;
lock (key) {
for(int i = 0; i < poolSize; i++) {
if(!useTable[i] && !object.ReferenceEquals(poolTable[i], null) && getCapacity(poolTable[i]) >= desiredCapacity) {
o = poolTable[i];
o.Clear();
useTable[i] = true;
break;
}
}
}
if(o == null) {
o = instantiateWithCapacity(desiredCapacity);
}
return new DisposableBundle<TCollection>(o, Release);
}
public IDisposable Get(int desiredCapacity, out TCollection collection) {
var bundle = Get(desiredCapacity);
collection = bundle.Object;
return bundle;
}
private void Release (TCollection o)
{
lock(key) {
var foundPlace = false;
//First try to find its place, if it's already in the pool table.
for(int i = 0; i < poolSize; i++) {
if(object.ReferenceEquals(poolTable[i], o)) {
useTable[i] = false;
foundPlace = true;
break;
}
}
//If that failed, than try to find an empty slot.
if(foundPlace == false) {
for(int i = 0; i < poolSize; i++) {
if(object.ReferenceEquals(poolTable[i], null)) {
poolTable[i] = o;
useTable[i] = false;
foundPlace = true;
break;
}
}
}
//If that failed, than try to find a smaller collection that isn't in use and replace it.
if(foundPlace == false) {
for(int i = 0; i < poolSize; i++) {
if(!useTable[i] && !object.ReferenceEquals(poolTable[i], null) && poolTable[i].Count < o.Count) {
poolTable[i] = o;
break;
}
}
}
}
}
}
}