com.alicizax.unity.framework/Runtime/ABase/MemoryPool/MemoryPoolRegistry.cs

167 lines
5.2 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
namespace AlicizaX
{
/// <summary>
/// 内存池注册表。非泛型路径通过此表查找对应的泛型池。
/// 注册发生在 MemoryPool&lt;T&gt; 静态构造器中,仅一次。
/// </summary>
public static class MemoryPoolRegistry
{
internal sealed class MemoryPoolHandle
{
public readonly Func<IMemory> Acquire;
public readonly Action<IMemory> Release;
public readonly Action Clear;
public readonly Action<int> Prewarm;
public readonly Func<MemoryPoolInfo> GetInfo;
public readonly Action<int> Tick;
public readonly Action<int> Shrink;
public MemoryPoolHandle(
Func<IMemory> acquire,
Action<IMemory> release,
Action clear,
Action<int> prewarm,
Func<MemoryPoolInfo> getInfo,
Action<int> tick,
Action<int> shrink)
{
Acquire = acquire;
Release = release;
Clear = clear;
Prewarm = prewarm;
GetInfo = getInfo;
Tick = tick;
Shrink = shrink;
}
}
private static readonly Dictionary<Type, MemoryPoolHandle> s_Handles
= new Dictionary<Type, MemoryPoolHandle>(64);
// Tick 回调用数组缓存,避免每帧遍历 Dictionary
private static Action<int>[] s_TickArray = Array.Empty<Action<int>>();
private static int s_TickCount;
private static bool s_TickArrayDirty;
public static int Count => s_Handles.Count;
internal static void Register(Type type, MemoryPoolHandle handle)
{
s_Handles[type] = handle;
s_TickArrayDirty = true;
}
/// <summary>
/// 非泛型 Acquire用于只有 Type 没有泛型参数的场景。
/// </summary>
public static IMemory Acquire(Type type)
{
if (s_Handles.TryGetValue(type, out var handle))
return handle.Acquire();
// 首次访问:触发 MemoryPool<T> 静态构造器
RuntimeHelpers.RunClassConstructor(
typeof(MemoryPool<>).MakeGenericType(type).TypeHandle);
if (s_Handles.TryGetValue(type, out handle))
return handle.Acquire();
throw new Exception($"MemoryPool: Type '{type.FullName}' is not a valid IMemory type.");
}
public static void Release(IMemory memory)
{
if (memory == null)
throw new ArgumentNullException(nameof(memory));
Type type = memory.GetType();
if (s_Handles.TryGetValue(type, out var handle))
{
handle.Release(memory);
return;
}
// 首次访问:触发静态构造器
RuntimeHelpers.RunClassConstructor(
typeof(MemoryPool<>).MakeGenericType(type).TypeHandle);
if (s_Handles.TryGetValue(type, out handle))
handle.Release(memory);
}
public static MemoryPoolInfo[] GetAllInfos()
{
var infos = new MemoryPoolInfo[s_Handles.Count];
int i = 0;
foreach (var kv in s_Handles)
infos[i++] = kv.Value.GetInfo();
return infos;
}
public static void ClearAll()
{
foreach (var kv in s_Handles)
kv.Value.Clear();
}
public static void Prewarm(Type type, int count)
{
if (s_Handles.TryGetValue(type, out var handle))
{
handle.Prewarm(count);
return;
}
RuntimeHelpers.RunClassConstructor(
typeof(MemoryPool<>).MakeGenericType(type).TypeHandle);
if (s_Handles.TryGetValue(type, out handle))
handle.Prewarm(count);
}
public static void ClearType(Type type)
{
if (s_Handles.TryGetValue(type, out var handle))
handle.Clear();
}
public static void RemoveFromType(Type type, int count)
{
if (s_Handles.TryGetValue(type, out var handle))
{
int unused = handle.GetInfo().UnusedCount;
handle.Shrink(unused - count);
}
}
/// <summary>
/// 每帧由 MemoryPoolTicker 调用,驱动所有池的自动回收。
/// </summary>
public static void TickAll(int frameCount)
{
if (s_TickArrayDirty)
RebuildTickArray();
for (int i = 0; i < s_TickCount; i++)
s_TickArray[i](frameCount);
}
private static void RebuildTickArray()
{
s_TickCount = s_Handles.Count;
if (s_TickArray.Length < s_TickCount)
s_TickArray = new Action<int>[s_TickCount];
int i = 0;
foreach (var kv in s_Handles)
s_TickArray[i++] = kv.Value.Tick;
s_TickArrayDirty = false;
}
}
}