using GFramework.Core.Abstractions.pool;
using GFramework.Core.system;
namespace GFramework.Core.pool;
///
/// 抽象对象池系统,提供基于键值的对象池管理功能
///
/// 对象池的键类型,必须不为null
/// 池化对象类型,必须实现IPoolableObject接口
public abstract class AbstractObjectPoolSystem
: AbstractSystem, IObjectPoolSystem where TObject : IPoolableObject where TKey : notnull
{
///
/// 池信息类,用于管理对象池的核心数据结构和统计信息。
/// 包含对象栈、容量限制以及各类操作的统计计数。
///
protected class PoolInfo
{
///
/// 对象栈,用于存储可复用的对象实例。
///
public Stack Stack { get; } = new();
///
/// 池的最大容量限制,超过此数量时将不再创建新对象。
///
public int MaxCapacity { get; set; }
///
/// 总共创建的对象数量统计。
///
public int TotalCreated { get; set; }
///
/// 总共从池中获取的对象数量统计。
///
public int TotalAcquired { get; set; }
///
/// 总共归还到池中的对象数量统计。
///
public int TotalReleased { get; set; }
///
/// 总共销毁的对象数量统计。
///
public int TotalDestroyed { get; set; }
///
/// 当前活跃(正在使用)的对象数量统计。
///
public int ActiveCount { get; set; }
}
///
/// 存储对象池的字典,键为池标识,值为池信息
///
protected readonly Dictionary Pools = new();
///
/// 获取对象池中的对象,如果池中没有可用对象则创建新的对象
///
/// 对象池的键值
/// 获取到的对象实例
public TObject Acquire(TKey key)
{
if (!Pools.TryGetValue(key, out var poolInfo))
{
poolInfo = new PoolInfo();
Pools[key] = poolInfo;
}
TObject obj;
if (poolInfo.Stack.Count > 0)
{
obj = poolInfo.Stack.Pop();
}
else
{
obj = Create(key);
poolInfo.TotalCreated++;
}
poolInfo.TotalAcquired++;
poolInfo.ActiveCount++;
obj.OnAcquire();
return obj;
}
///
/// 将对象释放回对象池中
///
/// 对象池的键值
/// 需要释放的对象
public void Release(TKey key, TObject obj)
{
obj.OnRelease();
if (!Pools.TryGetValue(key, out var poolInfo))
{
poolInfo = new PoolInfo();
Pools[key] = poolInfo;
}
poolInfo.TotalReleased++;
poolInfo.ActiveCount--;
// 检查容量限制
if (poolInfo.MaxCapacity > 0 && poolInfo.Stack.Count >= poolInfo.MaxCapacity)
{
// 超过容量限制,销毁对象
obj.OnPoolDestroy();
poolInfo.TotalDestroyed++;
}
else
{
poolInfo.Stack.Push(obj);
}
}
///
/// 清空所有对象池,销毁所有池中的对象并清理池容器
///
public void Clear()
{
// 遍历所有对象池,调用每个对象的销毁方法
foreach (var poolInfo in Pools.Values)
{
foreach (var obj in poolInfo.Stack)
{
obj.OnPoolDestroy();
}
}
Pools.Clear();
}
///
/// 获取指定池的当前大小
///
/// 对象池的键
/// 池中可用对象的数量
public int GetPoolSize(TKey key)
{
return Pools.TryGetValue(key, out var poolInfo) ? poolInfo.Stack.Count : 0;
}
///
/// 获取指定池的活跃对象数量
///
/// 对象池的键
/// 已被获取但未释放的对象数量
public int GetActiveCount(TKey key)
{
return Pools.TryGetValue(key, out var poolInfo) ? poolInfo.ActiveCount : 0;
}
///
/// 设置指定池的最大容量
///
/// 对象池的键
/// 最大容量,超过此容量的对象将被销毁而不是放回池中
public void SetMaxCapacity(TKey key, int maxCapacity)
{
if (!Pools.TryGetValue(key, out var poolInfo))
{
poolInfo = new PoolInfo();
Pools[key] = poolInfo;
}
poolInfo.MaxCapacity = maxCapacity;
}
///
/// 预热对象池,提前创建指定数量的对象
///
/// 对象池的键
/// 要预创建的对象数量
public void Prewarm(TKey key, int count)
{
if (!Pools.TryGetValue(key, out var poolInfo))
{
poolInfo = new PoolInfo();
Pools[key] = poolInfo;
}
for (var i = 0; i < count; i++)
{
var obj = Create(key);
poolInfo.TotalCreated++;
obj.OnRelease();
poolInfo.Stack.Push(obj);
}
}
///
/// 获取指定池的统计信息
///
/// 对象池的键
/// 池的统计信息
public PoolStatistics GetStatistics(TKey key)
{
if (!Pools.TryGetValue(key, out var poolInfo))
{
return new PoolStatistics
{
AvailableCount = 0,
ActiveCount = 0,
MaxCapacity = 0,
TotalCreated = 0,
TotalAcquired = 0,
TotalReleased = 0,
TotalDestroyed = 0
};
}
return new PoolStatistics
{
AvailableCount = poolInfo.Stack.Count,
ActiveCount = poolInfo.ActiveCount,
MaxCapacity = poolInfo.MaxCapacity,
TotalCreated = poolInfo.TotalCreated,
TotalAcquired = poolInfo.TotalAcquired,
TotalReleased = poolInfo.TotalReleased,
TotalDestroyed = poolInfo.TotalDestroyed
};
}
///
/// 创建一个新的对象实例(由子类决定怎么创建)
///
/// 用于创建对象的键值
/// 新创建的对象实例
protected abstract TObject Create(TKey key);
///
/// 系统销毁时的清理操作,清空所有对象池
///
protected override void OnDestroy()
{
Clear();
}
}