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

234 lines
7.1 KiB
C#
Raw Normal View History

2026-04-21 14:24:36 +08:00
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
namespace AlicizaX
{
2026-04-21 15:24:00 +08:00
2026-04-21 14:24:36 +08:00
public static class MemoryPoolRegistry
{
internal sealed class MemoryPoolHandle
{
2026-04-23 18:18:27 +08:00
public delegate IMemory AcquireHandler();
public delegate void ReleaseHandler(IMemory memory);
public delegate void ClearHandler();
public delegate void IntHandler(int value);
2026-04-23 19:09:56 +08:00
public delegate void GetInfoHandler(ref MemoryPoolInfo info);
2026-04-23 18:18:27 +08:00
public readonly AcquireHandler Acquire;
public readonly ReleaseHandler Release;
public readonly ClearHandler Clear;
public readonly IntHandler Prewarm;
public readonly GetInfoHandler GetInfo;
public readonly IntHandler Tick;
public readonly IntHandler Shrink;
2026-04-21 14:24:36 +08:00
public MemoryPoolHandle(
2026-04-23 18:18:27 +08:00
AcquireHandler acquire,
ReleaseHandler release,
ClearHandler clear,
IntHandler prewarm,
GetInfoHandler getInfo,
IntHandler tick,
IntHandler shrink)
2026-04-21 14:24:36 +08:00
{
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);
2026-04-23 18:18:27 +08:00
private static MemoryPoolHandle.IntHandler[] s_TickArray = Array.Empty<MemoryPoolHandle.IntHandler>();
2026-04-21 14:24:36 +08:00
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)
{
2026-04-23 18:18:27 +08:00
if (type == null)
throw new ArgumentNullException(nameof(type));
2026-04-21 14:24:36 +08:00
if (s_Handles.TryGetValue(type, out var handle))
return handle.Acquire();
2026-04-23 18:18:27 +08:00
EnsureRegistered(type);
2026-04-21 14:24:36 +08:00
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;
}
2026-04-23 18:18:27 +08:00
EnsureRegistered(type);
2026-04-21 14:24:36 +08:00
if (s_Handles.TryGetValue(type, out handle))
2026-04-23 18:18:27 +08:00
{
2026-04-21 14:24:36 +08:00
handle.Release(memory);
2026-04-23 18:18:27 +08:00
return;
}
throw new Exception($"MemoryPool: Type '{type.FullName}' is not a valid IMemory type.");
2026-04-21 14:24:36 +08:00
}
2026-04-23 19:09:56 +08:00
public static int GetAllInfos(MemoryPoolInfo[] infos)
2026-04-21 14:24:36 +08:00
{
2026-04-23 19:09:56 +08:00
if (infos == null)
throw new ArgumentNullException(nameof(infos));
int count = s_Handles.Count;
if (infos.Length < count)
throw new ArgumentException("Target buffer is too small.", nameof(infos));
2026-04-21 14:24:36 +08:00
int i = 0;
foreach (var kv in s_Handles)
2026-04-23 19:09:56 +08:00
{
kv.Value.GetInfo(ref infos[i]);
i++;
}
return count;
}
public static MemoryPoolInfo[] GetAllInfos()
{
var infos = new MemoryPoolInfo[s_Handles.Count];
GetAllInfos(infos);
2026-04-21 14:24:36 +08:00
return infos;
}
public static void ClearAll()
{
foreach (var kv in s_Handles)
kv.Value.Clear();
}
public static void Prewarm(Type type, int count)
{
2026-04-23 18:18:27 +08:00
if (type == null)
throw new ArgumentNullException(nameof(type));
2026-04-21 14:24:36 +08:00
if (s_Handles.TryGetValue(type, out var handle))
{
handle.Prewarm(count);
return;
}
2026-04-23 18:18:27 +08:00
EnsureRegistered(type);
2026-04-21 14:24:36 +08:00
if (s_Handles.TryGetValue(type, out handle))
2026-04-23 18:18:27 +08:00
{
2026-04-21 14:24:36 +08:00
handle.Prewarm(count);
2026-04-23 18:18:27 +08:00
return;
}
throw new Exception($"MemoryPool: Type '{type.FullName}' is not a valid IMemory type.");
2026-04-21 14:24:36 +08:00
}
public static void ClearType(Type type)
{
2026-04-23 18:18:27 +08:00
if (type == null)
throw new ArgumentNullException(nameof(type));
if (!s_Handles.TryGetValue(type, out var handle))
{
EnsureRegistered(type);
if (!s_Handles.TryGetValue(type, out handle))
throw new Exception($"MemoryPool: Type '{type.FullName}' is not a valid IMemory type.");
}
handle.Clear();
2026-04-21 14:24:36 +08:00
}
public static void RemoveFromType(Type type, int count)
{
2026-04-23 18:18:27 +08:00
if (type == null)
throw new ArgumentNullException(nameof(type));
2026-04-21 14:24:36 +08:00
if (s_Handles.TryGetValue(type, out var handle))
{
2026-04-23 19:09:56 +08:00
MemoryPoolInfo info = default;
handle.GetInfo(ref info);
int unused = info.UnusedCount;
2026-04-21 14:24:36 +08:00
handle.Shrink(unused - count);
2026-04-23 18:18:27 +08:00
return;
}
EnsureRegistered(type);
if (s_Handles.TryGetValue(type, out handle))
{
2026-04-23 19:09:56 +08:00
MemoryPoolInfo info = default;
handle.GetInfo(ref info);
int unused = info.UnusedCount;
2026-04-23 18:18:27 +08:00
handle.Shrink(unused - count);
return;
2026-04-21 14:24:36 +08:00
}
2026-04-23 18:18:27 +08:00
throw new Exception($"MemoryPool: Type '{type.FullName}' is not a valid IMemory type.");
2026-04-21 14:24:36 +08:00
}
2026-04-21 15:24:00 +08:00
2026-04-21 14:24:36 +08:00
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)
2026-04-23 18:18:27 +08:00
s_TickArray = new MemoryPoolHandle.IntHandler[s_TickCount];
2026-04-21 14:24:36 +08:00
int i = 0;
foreach (var kv in s_Handles)
s_TickArray[i++] = kv.Value.Tick;
s_TickArrayDirty = false;
}
2026-04-23 18:18:27 +08:00
private static void EnsureRegistered(Type type)
{
if (type == null)
throw new ArgumentNullException(nameof(type));
if (!typeof(IMemory).IsAssignableFrom(type))
throw new Exception($"MemoryPool: Type '{type.FullName}' is not a valid IMemory type.");
RuntimeHelpers.RunClassConstructor(
typeof(MemoryPool<>).MakeGenericType(type).TypeHandle);
}
2026-04-21 14:24:36 +08:00
}
}