优化ObjectPool和MemoryPool性能
优化热路径性能 O(1) 避免线性查找
This commit is contained in:
parent
46194ddee8
commit
d1d86adf09
@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using UnityEngine;
|
||||
|
||||
@ -14,8 +15,10 @@ namespace AlicizaX.ObjectPool
|
||||
public T Obj;
|
||||
public int SpawnCount;
|
||||
public float LastUseTime;
|
||||
public int NameHash;
|
||||
public int NextSameName;
|
||||
public int PrevByName;
|
||||
public int NextByName;
|
||||
public int PrevAvailableByName;
|
||||
public int NextAvailableByName;
|
||||
public int PrevUnused;
|
||||
public int NextUnused;
|
||||
public byte Flags;
|
||||
@ -37,7 +40,9 @@ namespace AlicizaX.ObjectPool
|
||||
private int m_FreeTop;
|
||||
|
||||
private readonly Dictionary<object, int> m_TargetMap;
|
||||
private IntOpenHashMap m_NameMap;
|
||||
private readonly Dictionary<string, int> m_AllNameHeadMap;
|
||||
private readonly Dictionary<string, int> m_AvailableNameHeadMap;
|
||||
private readonly Dictionary<string, int> m_AvailableNameTailMap;
|
||||
|
||||
private readonly bool m_AllowMultiSpawn;
|
||||
private float m_AutoReleaseInterval;
|
||||
@ -64,7 +69,9 @@ namespace AlicizaX.ObjectPool
|
||||
m_Slots = new ObjectSlot[initCap];
|
||||
m_FreeStack = new int[initCap];
|
||||
m_TargetMap = new Dictionary<object, int>(initCap, AlicizaX.ReferenceComparer<object>.Instance);
|
||||
m_NameMap = new IntOpenHashMap(initCap);
|
||||
m_AllNameHeadMap = new Dictionary<string, int>(initCap, StringComparer.Ordinal);
|
||||
m_AvailableNameHeadMap = new Dictionary<string, int>(initCap, StringComparer.Ordinal);
|
||||
m_AvailableNameTailMap = new Dictionary<string, int>(initCap, StringComparer.Ordinal);
|
||||
m_AllowMultiSpawn = allowMultiSpawn;
|
||||
m_AutoReleaseInterval = autoReleaseInterval;
|
||||
m_Capacity = capacity;
|
||||
@ -139,25 +146,32 @@ namespace AlicizaX.ObjectPool
|
||||
slot.Obj = obj;
|
||||
slot.SpawnCount = spawned ? 1 : 0;
|
||||
slot.LastUseTime = Time.realtimeSinceStartup;
|
||||
slot.NameHash = (obj.Name ?? string.Empty).GetHashCode();
|
||||
slot.NextSameName = -1;
|
||||
slot.PrevByName = -1;
|
||||
slot.NextByName = -1;
|
||||
slot.PrevAvailableByName = -1;
|
||||
slot.NextAvailableByName = -1;
|
||||
slot.PrevUnused = -1;
|
||||
slot.NextUnused = -1;
|
||||
slot.SetAlive(true);
|
||||
|
||||
m_TargetMap[obj.Target] = idx;
|
||||
|
||||
if (m_NameMap.TryGetValue(slot.NameHash, out int existingHead))
|
||||
slot.NextSameName = existingHead;
|
||||
m_NameMap.AddOrUpdate(slot.NameHash, idx);
|
||||
string objectName = obj.Name ?? string.Empty;
|
||||
if (m_AllNameHeadMap.TryGetValue(objectName, out int existingHead))
|
||||
{
|
||||
m_Slots[existingHead].PrevByName = idx;
|
||||
slot.NextByName = existingHead;
|
||||
}
|
||||
m_AllNameHeadMap[objectName] = idx;
|
||||
|
||||
obj.LastUseTime = slot.LastUseTime;
|
||||
if (spawned)
|
||||
obj.OnSpawn();
|
||||
else
|
||||
AddToUnusedList(idx);
|
||||
MarkSlotAvailable(idx);
|
||||
|
||||
if (Count > m_Capacity) MarkRelease(Count - m_Capacity);
|
||||
ValidateState();
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
@ -166,8 +180,10 @@ namespace AlicizaX.ObjectPool
|
||||
public T Spawn(string name)
|
||||
{
|
||||
if (name == null) throw new GameFrameworkException("Name is invalid.");
|
||||
int nameHash = name.GetHashCode();
|
||||
if (!m_NameMap.TryGetValue(nameHash, out int head)) return null;
|
||||
if (m_AllowMultiSpawn)
|
||||
return SpawnAny(name);
|
||||
|
||||
if (!m_AvailableNameHeadMap.TryGetValue(name, out int head)) return null;
|
||||
|
||||
float now = Time.realtimeSinceStartup;
|
||||
int current = head;
|
||||
@ -175,13 +191,14 @@ namespace AlicizaX.ObjectPool
|
||||
{
|
||||
ref var slot = ref m_Slots[current];
|
||||
if (slot.IsAlive() && string.Equals(slot.Obj.Name, name)
|
||||
&& (m_AllowMultiSpawn || slot.SpawnCount == 0))
|
||||
&& slot.SpawnCount == 0)
|
||||
{
|
||||
SpawnSlot(current, now);
|
||||
ValidateState();
|
||||
return slot.Obj;
|
||||
}
|
||||
|
||||
current = slot.NextSameName;
|
||||
current = slot.NextAvailableByName;
|
||||
}
|
||||
|
||||
return null;
|
||||
@ -193,17 +210,18 @@ namespace AlicizaX.ObjectPool
|
||||
public bool CanSpawn(string name)
|
||||
{
|
||||
if (name == null) throw new GameFrameworkException("Name is invalid.");
|
||||
int nameHash = name.GetHashCode();
|
||||
if (!m_NameMap.TryGetValue(nameHash, out int head)) return false;
|
||||
if (m_AllowMultiSpawn)
|
||||
return m_AllNameHeadMap.ContainsKey(name);
|
||||
|
||||
if (!m_AvailableNameHeadMap.TryGetValue(name, out int head)) return false;
|
||||
|
||||
int current = head;
|
||||
while (current >= 0)
|
||||
{
|
||||
ref var slot = ref m_Slots[current];
|
||||
if (slot.IsAlive() && string.Equals(slot.Obj.Name, name)
|
||||
&& (m_AllowMultiSpawn || slot.SpawnCount == 0))
|
||||
if (slot.IsAlive() && slot.SpawnCount == 0 && string.Equals(slot.Obj.Name, name))
|
||||
return true;
|
||||
current = slot.NextSameName;
|
||||
current = slot.NextAvailableByName;
|
||||
}
|
||||
|
||||
return false;
|
||||
@ -226,6 +244,7 @@ namespace AlicizaX.ObjectPool
|
||||
}
|
||||
|
||||
UnspawnSlot(idx);
|
||||
ValidateState();
|
||||
}
|
||||
|
||||
public override void Release()
|
||||
@ -258,6 +277,7 @@ namespace AlicizaX.ObjectPool
|
||||
{
|
||||
m_PendingReleaseCount = Math.Max(0, m_PendingReleaseCount - released);
|
||||
ShrinkStorageIfEmpty();
|
||||
ValidateState();
|
||||
}
|
||||
}
|
||||
|
||||
@ -301,7 +321,9 @@ namespace AlicizaX.ObjectPool
|
||||
}
|
||||
|
||||
m_TargetMap.Clear();
|
||||
m_NameMap.Clear();
|
||||
m_AllNameHeadMap.Clear();
|
||||
m_AvailableNameHeadMap.Clear();
|
||||
m_AvailableNameTailMap.Clear();
|
||||
m_SlotCount = 0;
|
||||
m_FreeTop = 0;
|
||||
m_PendingReleaseCount = 0;
|
||||
@ -309,6 +331,7 @@ namespace AlicizaX.ObjectPool
|
||||
m_UnusedTail = -1;
|
||||
m_LastBudgetScanStart = -1;
|
||||
m_IsShuttingDown = false;
|
||||
ValidateState();
|
||||
}
|
||||
|
||||
public override ObjectInfo[] GetAllObjectInfos()
|
||||
@ -351,7 +374,7 @@ namespace AlicizaX.ObjectPool
|
||||
{
|
||||
ref var slot = ref m_Slots[idx];
|
||||
if (slot.SpawnCount == 0)
|
||||
RemoveFromUnusedList(idx);
|
||||
MarkSlotUnavailable(idx);
|
||||
|
||||
slot.SpawnCount++;
|
||||
slot.LastUseTime = now;
|
||||
@ -371,7 +394,7 @@ namespace AlicizaX.ObjectPool
|
||||
if (slot.SpawnCount < 0)
|
||||
throw new GameFrameworkException($"Object '{slot.Obj.Name}' spawn count < 0.");
|
||||
if (slot.SpawnCount == 0)
|
||||
AddToUnusedList(idx);
|
||||
MarkSlotAvailable(idx);
|
||||
if (Count > m_Capacity && slot.SpawnCount == 0)
|
||||
MarkRelease(Count - m_Capacity);
|
||||
}
|
||||
@ -409,9 +432,9 @@ namespace AlicizaX.ObjectPool
|
||||
|
||||
T obj = slot.Obj;
|
||||
if (slot.SpawnCount == 0)
|
||||
RemoveFromUnusedList(idx);
|
||||
MarkSlotUnavailable(idx);
|
||||
|
||||
RemoveFromNameChain(idx);
|
||||
RemoveFromAllNameChain(idx);
|
||||
m_TargetMap.Remove(obj.Target);
|
||||
|
||||
obj.Release(false);
|
||||
@ -420,8 +443,10 @@ namespace AlicizaX.ObjectPool
|
||||
slot.Obj = null;
|
||||
slot.SetAlive(false);
|
||||
slot.SpawnCount = 0;
|
||||
slot.NameHash = 0;
|
||||
slot.NextSameName = -1;
|
||||
slot.PrevByName = -1;
|
||||
slot.NextByName = -1;
|
||||
slot.PrevAvailableByName = -1;
|
||||
slot.NextAvailableByName = -1;
|
||||
slot.PrevUnused = -1;
|
||||
slot.NextUnused = -1;
|
||||
|
||||
@ -432,34 +457,35 @@ namespace AlicizaX.ObjectPool
|
||||
ShrinkStorageIfEmpty();
|
||||
}
|
||||
|
||||
private void RemoveFromNameChain(int idx)
|
||||
private void RemoveFromAllNameChain(int idx)
|
||||
{
|
||||
ref var slot = ref m_Slots[idx];
|
||||
int nameHash = slot.NameHash;
|
||||
if (!m_NameMap.TryGetValue(nameHash, out int head)) return;
|
||||
string objectName = slot.Obj.Name ?? string.Empty;
|
||||
if (!m_AllNameHeadMap.TryGetValue(objectName, out int head))
|
||||
return;
|
||||
|
||||
if (head == idx)
|
||||
int prev = slot.PrevByName;
|
||||
int next = slot.NextByName;
|
||||
if (prev >= 0)
|
||||
{
|
||||
m_NameMap.Remove(nameHash);
|
||||
if (slot.NextSameName >= 0)
|
||||
m_NameMap.AddOrUpdate(nameHash, slot.NextSameName);
|
||||
m_Slots[prev].NextByName = next;
|
||||
}
|
||||
else
|
||||
{
|
||||
int current = head;
|
||||
while (current >= 0)
|
||||
{
|
||||
ref var chainSlot = ref m_Slots[current];
|
||||
if (chainSlot.NextSameName == idx)
|
||||
{
|
||||
chainSlot.NextSameName = slot.NextSameName;
|
||||
break;
|
||||
}
|
||||
current = chainSlot.NextSameName;
|
||||
}
|
||||
if (head != idx)
|
||||
throw new GameFrameworkException($"Object pool '{FullName}' all-name chain is inconsistent.");
|
||||
|
||||
if (next >= 0)
|
||||
m_AllNameHeadMap[objectName] = next;
|
||||
else
|
||||
m_AllNameHeadMap.Remove(objectName);
|
||||
}
|
||||
|
||||
slot.NextSameName = -1;
|
||||
if (next >= 0)
|
||||
m_Slots[next].PrevByName = prev;
|
||||
|
||||
slot.PrevByName = -1;
|
||||
slot.NextByName = -1;
|
||||
}
|
||||
|
||||
private int ReleaseUnused(int maxReleaseCount, bool requireExpired, float expireThreshold)
|
||||
@ -530,7 +556,9 @@ namespace AlicizaX.ObjectPool
|
||||
|
||||
m_Slots = new ObjectSlot[InitSlotCapacity];
|
||||
m_FreeStack = new int[InitSlotCapacity];
|
||||
m_NameMap = new IntOpenHashMap(InitSlotCapacity);
|
||||
m_AllNameHeadMap.Clear();
|
||||
m_AvailableNameHeadMap.Clear();
|
||||
m_AvailableNameTailMap.Clear();
|
||||
m_SlotCount = 0;
|
||||
m_FreeTop = 0;
|
||||
m_UnusedHead = -1;
|
||||
@ -538,45 +566,112 @@ namespace AlicizaX.ObjectPool
|
||||
m_LastBudgetScanStart = -1;
|
||||
}
|
||||
|
||||
private void AddToUnusedList(int idx)
|
||||
[Conditional("UNITY_EDITOR"), Conditional("DEVELOPMENT_BUILD")]
|
||||
private void ValidateState()
|
||||
{
|
||||
int aliveCount = 0;
|
||||
int unusedCount = 0;
|
||||
for (int i = 0; i < m_SlotCount; i++)
|
||||
{
|
||||
ref var slot = ref m_Slots[i];
|
||||
if (!slot.IsAlive())
|
||||
continue;
|
||||
|
||||
aliveCount++;
|
||||
|
||||
object target = slot.Obj.Target;
|
||||
if (!m_TargetMap.TryGetValue(target, out int mappedIdx) || mappedIdx != i)
|
||||
throw new GameFrameworkException($"Object pool '{FullName}' target index map is inconsistent.");
|
||||
|
||||
string objectName = slot.Obj.Name ?? string.Empty;
|
||||
if (!m_AllNameHeadMap.TryGetValue(objectName, out int head))
|
||||
throw new GameFrameworkException($"Object pool '{FullName}' all-name head is missing.");
|
||||
|
||||
if (slot.PrevByName < 0 && head != i)
|
||||
throw new GameFrameworkException($"Object pool '{FullName}' all-name chain head is inconsistent.");
|
||||
|
||||
if (slot.NextByName >= 0 && m_Slots[slot.NextByName].PrevByName != i)
|
||||
throw new GameFrameworkException($"Object pool '{FullName}' all-name chain link is inconsistent.");
|
||||
|
||||
bool inUnusedList = m_UnusedHead == i || slot.PrevUnused >= 0 || slot.NextUnused >= 0;
|
||||
bool inAvailableList = false;
|
||||
|
||||
if (slot.SpawnCount == 0)
|
||||
{
|
||||
unusedCount++;
|
||||
if (!inUnusedList)
|
||||
throw new GameFrameworkException($"Object pool '{FullName}' unused list is inconsistent.");
|
||||
|
||||
if (!m_AvailableNameHeadMap.TryGetValue(objectName, out int availableHead))
|
||||
throw new GameFrameworkException($"Object pool '{FullName}' available-name head is missing.");
|
||||
|
||||
inAvailableList = availableHead == i || slot.PrevAvailableByName >= 0 || slot.NextAvailableByName >= 0;
|
||||
if (!inAvailableList)
|
||||
throw new GameFrameworkException($"Object pool '{FullName}' available-name chain is inconsistent.");
|
||||
|
||||
if (slot.NextAvailableByName >= 0 && m_Slots[slot.NextAvailableByName].PrevAvailableByName != i)
|
||||
throw new GameFrameworkException($"Object pool '{FullName}' available-name link is inconsistent.");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (inUnusedList)
|
||||
throw new GameFrameworkException($"Object pool '{FullName}' spawned object exists in unused list.");
|
||||
|
||||
if (slot.PrevAvailableByName >= 0 || slot.NextAvailableByName >= 0)
|
||||
throw new GameFrameworkException($"Object pool '{FullName}' spawned object exists in available chain.");
|
||||
}
|
||||
}
|
||||
|
||||
if (aliveCount != m_TargetMap.Count)
|
||||
throw new GameFrameworkException($"Object pool '{FullName}' alive count is inconsistent.");
|
||||
|
||||
int walkUnusedCount = 0;
|
||||
int current = m_UnusedHead;
|
||||
int prevUnused = -1;
|
||||
while (current >= 0)
|
||||
{
|
||||
ref var slot = ref m_Slots[current];
|
||||
if (!slot.IsAlive() || slot.SpawnCount != 0)
|
||||
throw new GameFrameworkException($"Object pool '{FullName}' unused chain contains invalid slot.");
|
||||
if (slot.PrevUnused != prevUnused)
|
||||
throw new GameFrameworkException($"Object pool '{FullName}' unused chain linkage is inconsistent.");
|
||||
|
||||
walkUnusedCount++;
|
||||
prevUnused = current;
|
||||
current = slot.NextUnused;
|
||||
}
|
||||
|
||||
if (walkUnusedCount != unusedCount)
|
||||
throw new GameFrameworkException($"Object pool '{FullName}' unused chain count is inconsistent.");
|
||||
}
|
||||
|
||||
private void MarkSlotAvailable(int idx)
|
||||
{
|
||||
AddToUnusedListTail(idx);
|
||||
AddToAvailableNameChain(idx);
|
||||
}
|
||||
|
||||
private void MarkSlotUnavailable(int idx)
|
||||
{
|
||||
RemoveFromUnusedList(idx);
|
||||
RemoveFromAvailableNameChain(idx);
|
||||
}
|
||||
|
||||
private void AddToUnusedListTail(int idx)
|
||||
{
|
||||
ref var slot = ref m_Slots[idx];
|
||||
if (m_UnusedHead == idx || slot.PrevUnused >= 0 || slot.NextUnused >= 0)
|
||||
return;
|
||||
|
||||
if (m_UnusedTail >= 0 && m_Slots[m_UnusedTail].LastUseTime <= slot.LastUseTime)
|
||||
{
|
||||
slot.PrevUnused = m_UnusedTail;
|
||||
slot.NextUnused = -1;
|
||||
|
||||
if (m_UnusedTail >= 0)
|
||||
m_Slots[m_UnusedTail].NextUnused = idx;
|
||||
slot.PrevUnused = m_UnusedTail;
|
||||
slot.NextUnused = -1;
|
||||
m_UnusedTail = idx;
|
||||
}
|
||||
else
|
||||
{
|
||||
int current = m_UnusedHead;
|
||||
int prev = -1;
|
||||
while (current >= 0 && m_Slots[current].LastUseTime <= slot.LastUseTime)
|
||||
{
|
||||
prev = current;
|
||||
current = m_Slots[current].NextUnused;
|
||||
}
|
||||
m_UnusedHead = idx;
|
||||
|
||||
slot.PrevUnused = prev;
|
||||
slot.NextUnused = current;
|
||||
|
||||
if (prev >= 0)
|
||||
m_Slots[prev].NextUnused = idx;
|
||||
else
|
||||
m_UnusedHead = idx;
|
||||
|
||||
if (current >= 0)
|
||||
m_Slots[current].PrevUnused = idx;
|
||||
else
|
||||
m_UnusedTail = idx;
|
||||
|
||||
if (m_UnusedTail < 0)
|
||||
m_UnusedTail = idx;
|
||||
}
|
||||
m_UnusedTail = idx;
|
||||
}
|
||||
|
||||
private void RemoveFromUnusedList(int idx)
|
||||
@ -604,6 +699,75 @@ namespace AlicizaX.ObjectPool
|
||||
if (m_LastBudgetScanStart == idx)
|
||||
m_LastBudgetScanStart = next >= 0 ? next : m_UnusedHead;
|
||||
}
|
||||
|
||||
private void AddToAvailableNameChain(int idx)
|
||||
{
|
||||
ref var slot = ref m_Slots[idx];
|
||||
if (slot.PrevAvailableByName >= 0 || slot.NextAvailableByName >= 0)
|
||||
return;
|
||||
|
||||
string objectName = slot.Obj.Name ?? string.Empty;
|
||||
if (m_AvailableNameTailMap.TryGetValue(objectName, out int tail))
|
||||
{
|
||||
m_Slots[tail].NextAvailableByName = idx;
|
||||
slot.PrevAvailableByName = tail;
|
||||
slot.NextAvailableByName = -1;
|
||||
m_AvailableNameTailMap[objectName] = idx;
|
||||
}
|
||||
else
|
||||
{
|
||||
slot.PrevAvailableByName = -1;
|
||||
slot.NextAvailableByName = -1;
|
||||
m_AvailableNameHeadMap[objectName] = idx;
|
||||
m_AvailableNameTailMap[objectName] = idx;
|
||||
}
|
||||
}
|
||||
|
||||
private void RemoveFromAvailableNameChain(int idx)
|
||||
{
|
||||
ref var slot = ref m_Slots[idx];
|
||||
string objectName = slot.Obj.Name ?? string.Empty;
|
||||
if (slot.PrevAvailableByName < 0
|
||||
&& slot.NextAvailableByName < 0
|
||||
&& (!m_AvailableNameHeadMap.TryGetValue(objectName, out int head) || head != idx))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int prev = slot.PrevAvailableByName;
|
||||
int next = slot.NextAvailableByName;
|
||||
|
||||
if (prev >= 0)
|
||||
m_Slots[prev].NextAvailableByName = next;
|
||||
else if (next >= 0)
|
||||
m_AvailableNameHeadMap[objectName] = next;
|
||||
else
|
||||
m_AvailableNameHeadMap.Remove(objectName);
|
||||
|
||||
if (next >= 0)
|
||||
m_Slots[next].PrevAvailableByName = prev;
|
||||
else if (prev >= 0)
|
||||
m_AvailableNameTailMap[objectName] = prev;
|
||||
else
|
||||
m_AvailableNameTailMap.Remove(objectName);
|
||||
|
||||
slot.PrevAvailableByName = -1;
|
||||
slot.NextAvailableByName = -1;
|
||||
}
|
||||
|
||||
private T SpawnAny(string name)
|
||||
{
|
||||
if (!m_AllNameHeadMap.TryGetValue(name, out int head))
|
||||
return null;
|
||||
|
||||
float now = Time.realtimeSinceStartup;
|
||||
ref var slot = ref m_Slots[head];
|
||||
if (!slot.IsAlive() || !string.Equals(slot.Obj.Name, name, StringComparison.Ordinal))
|
||||
return null;
|
||||
|
||||
SpawnSlot(head, now);
|
||||
return slot.Obj;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,11 +8,13 @@ namespace AlicizaX.ObjectPool
|
||||
[UnityEngine.Scripting.Preserve]
|
||||
internal sealed partial class ObjectPoolService : ServiceBase, IObjectPoolService, IServiceTickable
|
||||
{
|
||||
private const float DefaultAutoReleaseInterval = float.MaxValue;
|
||||
private const int DefaultCapacity = int.MaxValue;
|
||||
private const float DefaultExpireTime = float.MaxValue;
|
||||
|
||||
private readonly Dictionary<TypeNamePair, ObjectPoolBase> m_ObjectPools;
|
||||
private readonly List<ObjectPoolBase> m_ObjectPoolList;
|
||||
private readonly Dictionary<ObjectPoolBase, int> m_ObjectPoolIndexMap;
|
||||
private readonly List<ObjectPoolBase> m_CachedAllObjectPools;
|
||||
private readonly Comparison<ObjectPoolBase> m_ObjectPoolComparer;
|
||||
|
||||
@ -20,6 +22,7 @@ namespace AlicizaX.ObjectPool
|
||||
{
|
||||
m_ObjectPools = new Dictionary<TypeNamePair, ObjectPoolBase>();
|
||||
m_ObjectPoolList = new List<ObjectPoolBase>();
|
||||
m_ObjectPoolIndexMap = new Dictionary<ObjectPoolBase, int>(AlicizaX.ReferenceComparer<ObjectPoolBase>.Instance);
|
||||
m_CachedAllObjectPools = new List<ObjectPoolBase>();
|
||||
m_ObjectPoolComparer = ObjectPoolComparer;
|
||||
}
|
||||
@ -41,6 +44,7 @@ namespace AlicizaX.ObjectPool
|
||||
m_ObjectPoolList[i].Shutdown();
|
||||
m_ObjectPools.Clear();
|
||||
m_ObjectPoolList.Clear();
|
||||
m_ObjectPoolIndexMap.Clear();
|
||||
m_CachedAllObjectPools.Clear();
|
||||
}
|
||||
|
||||
@ -117,12 +121,13 @@ namespace AlicizaX.ObjectPool
|
||||
var pool = new ObjectPool<T>(
|
||||
options.Name ?? string.Empty,
|
||||
options.AllowMultiSpawn,
|
||||
options.AutoReleaseInterval ?? DefaultExpireTime,
|
||||
options.AutoReleaseInterval ?? DefaultAutoReleaseInterval,
|
||||
options.Capacity ?? DefaultCapacity,
|
||||
options.ExpireTime ?? DefaultExpireTime,
|
||||
options.Priority);
|
||||
|
||||
m_ObjectPools.Add(key, pool);
|
||||
m_ObjectPoolIndexMap.Add(pool, m_ObjectPoolList.Count);
|
||||
m_ObjectPoolList.Add(pool);
|
||||
return pool;
|
||||
}
|
||||
@ -138,12 +143,13 @@ namespace AlicizaX.ObjectPool
|
||||
var pool = (ObjectPoolBase)Activator.CreateInstance(poolType,
|
||||
options.Name ?? string.Empty,
|
||||
options.AllowMultiSpawn,
|
||||
options.AutoReleaseInterval ?? DefaultExpireTime,
|
||||
options.AutoReleaseInterval ?? DefaultAutoReleaseInterval,
|
||||
options.Capacity ?? DefaultCapacity,
|
||||
options.ExpireTime ?? DefaultExpireTime,
|
||||
options.Priority);
|
||||
|
||||
m_ObjectPools.Add(key, pool);
|
||||
m_ObjectPoolIndexMap.Add(pool, m_ObjectPoolList.Count);
|
||||
m_ObjectPoolList.Add(pool);
|
||||
return pool;
|
||||
}
|
||||
@ -217,12 +223,27 @@ namespace AlicizaX.ObjectPool
|
||||
if (m_ObjectPools.TryGetValue(key, out var pool))
|
||||
{
|
||||
pool.Shutdown();
|
||||
m_ObjectPoolList.Remove(pool);
|
||||
RemovePoolFromList(pool);
|
||||
m_ObjectPoolIndexMap.Remove(pool);
|
||||
return m_ObjectPools.Remove(key);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void RemovePoolFromList(ObjectPoolBase pool)
|
||||
{
|
||||
if (!m_ObjectPoolIndexMap.TryGetValue(pool, out int index))
|
||||
return;
|
||||
|
||||
int lastIndex = m_ObjectPoolList.Count - 1;
|
||||
ObjectPoolBase lastPool = m_ObjectPoolList[lastIndex];
|
||||
m_ObjectPoolList[index] = lastPool;
|
||||
m_ObjectPoolList.RemoveAt(lastIndex);
|
||||
|
||||
if (!ReferenceEquals(lastPool, pool))
|
||||
m_ObjectPoolIndexMap[lastPool] = index;
|
||||
}
|
||||
|
||||
private static void ValidateObjectType(Type objectType)
|
||||
{
|
||||
if (objectType == null)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user