Files
Convention-Unity/Convention/[Runtime]/Convention.ReferencePool.cs

490 lines
15 KiB
C#
Raw Normal View History

2025-11-20 17:29:16 +08:00
using Convention.Experimental.PublicType;
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace Convention.ReferenceManagement
{
/// <summary>
/// <20><><EFBFBD>ýӿ<C3BD>
/// </summary>
public interface IReference
{
/// <summary>
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/// </summary>
void Clear();
}
/// <summary>
/// <20><><EFBFBD>ó<EFBFBD>
/// </summary>
public static partial class ReferencePool
{
private static bool m_EnableStrictCheck = false;
/// <summary>
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD>ǿ<EFBFBD>Ƽ<EFBFBD><C6BC><EFBFBD>
/// </summary>
public static bool EnableStrictCheck
{
get
{
return m_EnableStrictCheck;
}
set
{
m_EnableStrictCheck = value;
}
}
private sealed class ReferenceCollection
{
private readonly Queue<IReference> m_References;
private readonly Type m_ReferenceType;
private int m_UsingReferenceCount;
private int m_AcquireReferenceCount;
private int m_ReleaseReferenceCount;
private int m_AddReferenceCount;
private int m_RemoveReferenceCount;
public ReferenceCollection(Type referenceType)
{
m_References = new Queue<IReference>();
m_ReferenceType = referenceType;
m_UsingReferenceCount = 0;
m_AcquireReferenceCount = 0;
m_ReleaseReferenceCount = 0;
m_AddReferenceCount = 0;
m_RemoveReferenceCount = 0;
}
public Type ReferenceType
{
get
{
return m_ReferenceType;
}
}
public int UnusedReferenceCount
{
get
{
return m_References.Count;
}
}
public int UsingReferenceCount
{
get
{
return m_UsingReferenceCount;
}
}
public int AcquireReferenceCount
{
get
{
return m_AcquireReferenceCount;
}
}
public int ReleaseReferenceCount
{
get
{
return m_ReleaseReferenceCount;
}
}
public int AddReferenceCount
{
get
{
return m_AddReferenceCount;
}
}
public int RemoveReferenceCount
{
get
{
return m_RemoveReferenceCount;
}
}
public T Acquire<T>() where T : class, IReference, new()
{
if (typeof(T) != m_ReferenceType)
{
throw new GameException("Type is invalid.");
}
m_UsingReferenceCount++;
m_AcquireReferenceCount++;
lock (m_References)
{
if (m_References.Count > 0)
{
return (T)m_References.Dequeue();
}
}
m_AddReferenceCount++;
return new T();
}
public IReference Acquire()
{
m_UsingReferenceCount++;
m_AcquireReferenceCount++;
lock (m_References)
{
if (m_References.Count > 0)
{
return m_References.Dequeue();
}
}
m_AddReferenceCount++;
return (IReference)Activator.CreateInstance(m_ReferenceType);
}
public void Release(IReference reference)
{
reference.Clear();
lock (m_References)
{
if (m_EnableStrictCheck && m_References.Contains(reference))
{
throw new GameException("The reference has been released.");
}
m_References.Enqueue(reference);
}
m_ReleaseReferenceCount++;
m_UsingReferenceCount--;
}
public void Add<T>(int count) where T : class, IReference, new()
{
if (typeof(T) != m_ReferenceType)
{
throw new GameException("Type is invalid.");
}
lock (m_References)
{
m_AddReferenceCount += count;
while (count-- > 0)
{
m_References.Enqueue(new T());
}
}
}
public void Add(int count)
{
lock (m_References)
{
m_AddReferenceCount += count;
while (count-- > 0)
{
m_References.Enqueue((IReference)Activator.CreateInstance(m_ReferenceType));
}
}
}
public void Remove(int count)
{
lock (m_References)
{
if (count > m_References.Count)
{
count = m_References.Count;
}
m_RemoveReferenceCount += count;
while (count-- > 0)
{
m_References.Dequeue();
}
}
}
public void RemoveAll()
{
lock (m_References)
{
m_RemoveReferenceCount += m_References.Count;
m_References.Clear();
}
}
}
private static readonly Dictionary<Type, ReferenceCollection> s_ReferenceCollections = new();
/// <summary>
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD>óص<C3B3><D8B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/// </summary>
public static int Count
{
get
{
return s_ReferenceCollections.Count;
}
}
/// <summary>
/// <20><><EFBFBD>ó<EFBFBD><C3B3><EFBFBD>Ϣ
/// </summary>
[StructLayout(LayoutKind.Auto)]
public readonly struct ReferencePoolInfo
{
/// <summary>
/// <20><><EFBFBD>ó<EFBFBD><C3B3><EFBFBD><EFBFBD><EFBFBD>
/// </summary>
public readonly Type Type;
/// <summary>
/// δʹ<CEB4><CAB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/// </summary>
public readonly int UnusedReferenceCount;
/// <summary>
/// <20><><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/// </summary>
public readonly int UsingReferenceCount;
/// <summary>
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/// </summary>
public readonly int AcquireReferenceCount;
/// <summary>
/// <20><EFBFBD><E9BBB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/// </summary>
public readonly int ReleaseReferenceCount;
/// <summary>
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/// </summary>
public readonly int AddReferenceCount;
/// <summary>
/// <20>Ƴ<EFBFBD><C6B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/// </summary>
public readonly int RemoveReferenceCount;
/// <summary>
/// <20><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD>ó<EFBFBD><C3B3><EFBFBD>Ϣ<EFBFBD><CFA2><EFBFBD><EFBFBD>ʵ<EFBFBD><CAB5><EFBFBD><EFBFBD>
/// </summary>
/// <param name="type"><3E><><EFBFBD>ó<EFBFBD><C3B3><EFBFBD><EFBFBD>͡<EFBFBD></param>
/// <param name="unusedReferenceCount">δʹ<CEB4><CAB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD></param>
/// <param name="usingReferenceCount"><3E><><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD></param>
/// <param name="acquireReferenceCount"><3E><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD></param>
/// <param name="releaseReferenceCount"><3E><EFBFBD><E9BBB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD></param>
/// <param name="addReferenceCount"><3E><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD></param>
/// <param name="removeReferenceCount"><3E>Ƴ<EFBFBD><C6B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD></param>
public ReferencePoolInfo(Type type,
int unusedReferenceCount,
int usingReferenceCount,
int acquireReferenceCount,
int releaseReferenceCount,
int addReferenceCount,
int removeReferenceCount)
{
this.Type = type;
this.UnusedReferenceCount = unusedReferenceCount;
this.UsingReferenceCount = usingReferenceCount;
this.AcquireReferenceCount = acquireReferenceCount;
this.ReleaseReferenceCount = releaseReferenceCount;
this.AddReferenceCount = addReferenceCount;
this.RemoveReferenceCount = removeReferenceCount;
}
}
/// <summary>
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>óص<C3B3><D8B5><EFBFBD>Ϣ
/// </summary>
/// <returns><3E><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>óص<C3B3><D8B5><EFBFBD>Ϣ</returns>
public static ReferencePoolInfo[] GetAllReferencePoolInfos()
{
int index = 0;
ReferencePoolInfo[] results = null;
lock (s_ReferenceCollections)
{
results = new ReferencePoolInfo[s_ReferenceCollections.Count];
foreach (var (key, value) in s_ReferenceCollections)
{
results[index++] = new ReferencePoolInfo(key,
value.UnusedReferenceCount,
value.UsingReferenceCount,
value.AcquireReferenceCount,
value.ReleaseReferenceCount,
value.AddReferenceCount,
value.RemoveReferenceCount);
}
}
return results;
}
/// <summary>
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ó<EFBFBD>
/// </summary>
public static void ClearAll()
{
lock (s_ReferenceCollections)
{
foreach (var (_, value) in s_ReferenceCollections)
{
value.RemoveAll();
}
s_ReferenceCollections.Clear();
}
}
private static ReferenceCollection GetReferenceCollection(Type referenceType)
{
if (referenceType == null)
{
throw new GameException("ReferenceType is invalid.");
}
ReferenceCollection referenceCollection = null;
lock (s_ReferenceCollections)
{
if (!s_ReferenceCollections.TryGetValue(referenceType, out referenceCollection))
{
referenceCollection = new ReferenceCollection(referenceType);
s_ReferenceCollections.Add(referenceType, referenceCollection);
}
}
return referenceCollection;
}
private static void InternalCheckReferenceType(Type referenceType)
{
if (!m_EnableStrictCheck)
{
return;
}
if (referenceType == null)
{
throw new GameException("Reference type is invalid.");
}
if (!referenceType.IsClass || referenceType.IsAbstract)
{
throw new GameException("Reference type is not a non-abstract class type.");
}
if (!typeof(IReference).IsAssignableFrom(referenceType))
{
throw new GameException($"Reference type '{referenceType.FullName}' is invalid.");
}
}
/// <summary>
/// <20><><EFBFBD><EFBFBD><EFBFBD>óػ<C3B3>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>
/// </summary>
/// <param name="referenceType"><3E><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD></param>
/// <returns><3E><><EFBFBD><EFBFBD></returns>
public static IReference Acquire(Type referenceType)
{
InternalCheckReferenceType(referenceType);
return GetReferenceCollection(referenceType).Acquire();
}
/// <summary>
/// <20><><EFBFBD><EFBFBD><EFBFBD>óػ<C3B3>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>
/// </summary>
/// <typeparam name="T"><3E><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD></typeparam>
/// <returns><3E><><EFBFBD><EFBFBD></returns>
public static T Acquire<T>() where T : class, IReference, new()
{
return GetReferenceCollection(typeof(T)).Acquire<T>();
}
/// <summary>
/// <20><><EFBFBD><EFBFBD><EFBFBD>ù黹<C3B9><E9BBB9><EFBFBD>ó<EFBFBD>
/// </summary>
/// <param name="reference"><3E><><EFBFBD><EFBFBD></param>
public static void Release(IReference reference)
{
if (reference == null)
{
throw new GameException("Reference is invalid.");
}
Type referenceType = reference.GetType();
InternalCheckReferenceType(referenceType);
GetReferenceCollection(referenceType).Release(reference);
}
/// <summary>
/// <20><><EFBFBD><EFBFBD><EFBFBD>ó<EFBFBD><C3B3><EFBFBD>׷<EFBFBD><D7B7>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/// </summary>
/// <typeparam name="T"><3E><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD></typeparam>
/// <param name="count">׷<><D7B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD></param>
public static void Add<T>(int count) where T : class, IReference, new()
{
GetReferenceCollection(typeof(T)).Add<T>(count);
}
/// <summary>
/// <20><><EFBFBD><EFBFBD><EFBFBD>ó<EFBFBD><C3B3><EFBFBD>׷<EFBFBD><D7B7>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/// </summary>
/// <param name="referenceType"><3E><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD></param>
/// <param name="count">׷<><D7B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD></param>
public static void Add(Type referenceType, int count)
{
InternalCheckReferenceType(referenceType);
GetReferenceCollection(referenceType).Add(count);
}
/// <summary>
/// <20><><EFBFBD><EFBFBD><EFBFBD>ó<EFBFBD><C3B3><EFBFBD><EFBFBD>Ƴ<EFBFBD>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/// </summary>
/// <typeparam name="T"><3E><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD></typeparam>
/// <param name="count"><3E>Ƴ<EFBFBD><C6B3><EFBFBD><EFBFBD><EFBFBD></param>
public static void Remove<T>(int count) where T : class, IReference
{
GetReferenceCollection(typeof(T)).Remove(count);
}
/// <summary>
/// <20><><EFBFBD><EFBFBD><EFBFBD>ó<EFBFBD><C3B3><EFBFBD><EFBFBD>Ƴ<EFBFBD>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/// </summary>
/// <param name="referenceType"><3E><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD></param>
/// <param name="count"><3E>Ƴ<EFBFBD><C6B3><EFBFBD><EFBFBD><EFBFBD></param>
public static void Remove(Type referenceType, int count)
{
InternalCheckReferenceType(referenceType);
GetReferenceCollection(referenceType).Remove(count);
}
/// <summary>
/// <20><><EFBFBD><EFBFBD><EFBFBD>ó<EFBFBD><C3B3><EFBFBD><EFBFBD>Ƴ<EFBFBD><C6B3><EFBFBD><EFBFBD>е<EFBFBD><D0B5><EFBFBD><EFBFBD><EFBFBD>
/// </summary>
/// <typeparam name="T"><3E><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD></typeparam>
public static void RemoveAll<T>() where T : class, IReference
{
GetReferenceCollection(typeof(T)).RemoveAll();
}
/// <summary>
/// <20><><EFBFBD><EFBFBD><EFBFBD>ó<EFBFBD><C3B3><EFBFBD><EFBFBD>Ƴ<EFBFBD><C6B3><EFBFBD><EFBFBD>е<EFBFBD><D0B5><EFBFBD><EFBFBD>á<EFBFBD>
/// </summary>
/// <param name="referenceType"><3E><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>͡<EFBFBD></param>
public static void RemoveAll(Type referenceType)
{
InternalCheckReferenceType(referenceType);
GetReferenceCollection(referenceType).RemoveAll();
}
}
}