2025-02-07 16:04:12 +08:00
using System ;
using System.Collections.Generic ;
2025-03-24 13:16:51 +08:00
using AlicizaX ;
2025-02-07 16:04:12 +08:00
namespace AlicizaX.ObjectPool
{
2025-03-20 20:47:11 +08:00
internal sealed partial class ObjectPoolModule : IObjectPoolModule
2025-02-07 16:04:12 +08:00
{
/// <summary>
/// 对象池。
/// </summary>
/// <typeparam name="T">对象类型。</typeparam>
private sealed class ObjectPool < T > : ObjectPoolBase , IObjectPool < T > where T : ObjectBase
{
private readonly GameFrameworkMultiDictionary < string , Object < T > > m_Objects ;
private readonly Dictionary < object , Object < T > > m_ObjectMap ;
private readonly ReleaseObjectFilterCallback < T > m_DefaultReleaseObjectFilterCallback ;
private readonly List < T > m_CachedCanReleaseObjects ;
private readonly List < T > m_CachedToReleaseObjects ;
private readonly bool m_AllowMultiSpawn ;
private float m_AutoReleaseInterval ;
private int m_Capacity ;
private float m_ExpireTime ;
private int m_Priority ;
private float m_AutoReleaseTime ;
/// <summary>
/// 初始化对象池的新实例。
/// </summary>
/// <param name="name">对象池名称。</param>
/// <param name="allowMultiSpawn">是否允许对象被多次获取。</param>
/// <param name="autoReleaseInterval">对象池自动释放可释放对象的间隔秒数。</param>
/// <param name="capacity">对象池的容量。</param>
/// <param name="expireTime">对象池对象过期秒数。</param>
/// <param name="priority">对象池的优先级。</param>
public ObjectPool ( string name , bool allowMultiSpawn , float autoReleaseInterval , int capacity , float expireTime , int priority )
: base ( name )
{
m_Objects = new GameFrameworkMultiDictionary < string , Object < T > > ( ) ;
m_ObjectMap = new Dictionary < object , Object < T > > ( ) ;
m_DefaultReleaseObjectFilterCallback = DefaultReleaseObjectFilterCallback ;
m_CachedCanReleaseObjects = new List < T > ( ) ;
m_CachedToReleaseObjects = new List < T > ( ) ;
m_AllowMultiSpawn = allowMultiSpawn ;
m_AutoReleaseInterval = autoReleaseInterval ;
Capacity = capacity ;
ExpireTime = expireTime ;
m_Priority = priority ;
m_AutoReleaseTime = 0f ;
}
/// <summary>
/// 获取对象池对象类型。
/// </summary>
public override Type ObjectType
{
get { return typeof ( T ) ; }
}
/// <summary>
/// 获取对象池中对象的数量。
/// </summary>
public override int Count
{
get { return m_ObjectMap . Count ; }
}
/// <summary>
/// 获取对象池中能被释放的对象的数量。
/// </summary>
public override int CanReleaseCount
{
get
{
GetCanReleaseObjects ( m_CachedCanReleaseObjects ) ;
return m_CachedCanReleaseObjects . Count ;
}
}
/// <summary>
/// 获取是否允许对象被多次获取。
/// </summary>
public override bool AllowMultiSpawn
{
get { return m_AllowMultiSpawn ; }
}
/// <summary>
/// 获取或设置对象池自动释放可释放对象的间隔秒数。
/// </summary>
public override float AutoReleaseInterval
{
get { return m_AutoReleaseInterval ; }
set { m_AutoReleaseInterval = value ; }
}
/// <summary>
/// 获取或设置对象池的容量。
/// </summary>
public override int Capacity
{
get { return m_Capacity ; }
set
{
if ( value < 0 )
{
throw new GameFrameworkException ( "Capacity is invalid." ) ;
}
if ( m_Capacity = = value )
{
return ;
}
m_Capacity = value ;
Release ( ) ;
}
}
/// <summary>
/// 获取或设置对象池对象过期秒数。
/// </summary>
public override float ExpireTime
{
get { return m_ExpireTime ; }
set
{
if ( value < 0f )
{
throw new GameFrameworkException ( "ExpireTime is invalid." ) ;
}
if ( ExpireTime = = value )
{
return ;
}
m_ExpireTime = value ;
Release ( ) ;
}
}
/// <summary>
/// 获取或设置对象池的优先级。
/// </summary>
public override int Priority
{
get { return m_Priority ; }
set { m_Priority = value ; }
}
/// <summary>
/// 创建对象。
/// </summary>
/// <param name="obj">对象。</param>
/// <param name="spawned">对象是否已被获取。</param>
public void Register ( T obj , bool spawned )
{
if ( obj = = null )
{
throw new GameFrameworkException ( "Object is invalid." ) ;
}
Object < T > internalObject = Object < T > . Create ( obj , spawned ) ;
m_Objects . Add ( obj . Name , internalObject ) ;
m_ObjectMap . Add ( obj . Target , internalObject ) ;
if ( Count > m_Capacity )
{
Release ( ) ;
}
}
/// <summary>
/// 检查对象。
/// </summary>
/// <returns>要检查的对象是否存在。</returns>
public bool CanSpawn ( )
{
return CanSpawn ( string . Empty ) ;
}
/// <summary>
/// 检查对象。
/// </summary>
/// <param name="name">对象名称。</param>
/// <returns>要检查的对象是否存在。</returns>
public bool CanSpawn ( string name )
{
if ( name = = null )
{
throw new GameFrameworkException ( "Name is invalid." ) ;
}
GameFrameworkLinkedListRange < Object < T > > objectRange = default ( GameFrameworkLinkedListRange < Object < T > > ) ;
if ( m_Objects . TryGetValue ( name , out objectRange ) )
{
foreach ( Object < T > internalObject in objectRange )
{
if ( m_AllowMultiSpawn | | ! internalObject . IsInUse )
{
return true ;
}
}
}
return false ;
}
/// <summary>
/// 获取对象。
/// </summary>
/// <returns>要获取的对象。</returns>
public T Spawn ( )
{
return Spawn ( string . Empty ) ;
}
/// <summary>
/// 获取对象。
/// </summary>
/// <param name="name">对象名称。</param>
/// <returns>要获取的对象。</returns>
public T Spawn ( string name )
{
if ( name = = null )
{
throw new GameFrameworkException ( "Name is invalid." ) ;
}
GameFrameworkLinkedListRange < Object < T > > objectRange = default ( GameFrameworkLinkedListRange < Object < T > > ) ;
if ( m_Objects . TryGetValue ( name , out objectRange ) )
{
foreach ( Object < T > internalObject in objectRange )
{
if ( m_AllowMultiSpawn | | ! internalObject . IsInUse )
{
return internalObject . Spawn ( ) ;
}
}
}
return null ;
}
/// <summary>
/// 回收对象。
/// </summary>
/// <param name="obj">要回收的对象。</param>
public void Unspawn ( T obj )
{
if ( obj = = null )
{
throw new GameFrameworkException ( "Object is invalid." ) ;
}
Unspawn ( obj . Target ) ;
}
/// <summary>
/// 回收对象。
/// </summary>
/// <param name="target">要回收的对象。</param>
public void Unspawn ( object target )
{
if ( target = = null )
{
throw new GameFrameworkException ( "Target is invalid." ) ;
}
Object < T > internalObject = GetObject ( target ) ;
if ( internalObject ! = null )
{
internalObject . Unspawn ( ) ;
if ( Count > m_Capacity & & internalObject . SpawnCount < = 0 )
{
Release ( ) ;
}
}
else
{
throw new GameFrameworkException ( Utility . Text . Format ( "Can not find target in object pool '{0}', target type is '{1}', target value is '{2}'." , new TypeNamePair ( typeof ( T ) , Name ) , target . GetType ( ) . FullName , target ) ) ;
}
}
/// <summary>
/// 设置对象是否被加锁。
/// </summary>
/// <param name="obj">要设置被加锁的对象。</param>
/// <param name="locked">是否被加锁。</param>
public void SetLocked ( T obj , bool locked )
{
if ( obj = = null )
{
throw new GameFrameworkException ( "Object is invalid." ) ;
}
SetLocked ( obj . Target , locked ) ;
}
/// <summary>
/// 设置对象是否被加锁。
/// </summary>
/// <param name="target">要设置被加锁的对象。</param>
/// <param name="locked">是否被加锁。</param>
public void SetLocked ( object target , bool locked )
{
if ( target = = null )
{
throw new GameFrameworkException ( "Target is invalid." ) ;
}
Object < T > internalObject = GetObject ( target ) ;
if ( internalObject ! = null )
{
internalObject . Locked = locked ;
}
else
{
throw new GameFrameworkException ( Utility . Text . Format ( "Can not find target in object pool '{0}', target type is '{1}', target value is '{2}'." , new TypeNamePair ( typeof ( T ) , Name ) , target . GetType ( ) . FullName , target ) ) ;
}
}
/// <summary>
/// 设置对象的优先级。
/// </summary>
/// <param name="obj">要设置优先级的对象。</param>
/// <param name="priority">优先级。</param>
public void SetPriority ( T obj , int priority )
{
if ( obj = = null )
{
throw new GameFrameworkException ( "Object is invalid." ) ;
}
SetPriority ( obj . Target , priority ) ;
}
/// <summary>
/// 设置对象的优先级。
/// </summary>
/// <param name="target">要设置优先级的对象。</param>
/// <param name="priority">优先级。</param>
public void SetPriority ( object target , int priority )
{
if ( target = = null )
{
throw new GameFrameworkException ( "Target is invalid." ) ;
}
Object < T > internalObject = GetObject ( target ) ;
if ( internalObject ! = null )
{
internalObject . Priority = priority ;
}
else
{
throw new GameFrameworkException ( Utility . Text . Format ( "Can not find target in object pool '{0}', target type is '{1}', target value is '{2}'." , new TypeNamePair ( typeof ( T ) , Name ) , target . GetType ( ) . FullName , target ) ) ;
}
}
/// <summary>
/// 释放对象。
/// </summary>
/// <param name="obj">要释放的对象。</param>
/// <returns>释放对象是否成功。</returns>
public bool ReleaseObject ( T obj )
{
if ( obj = = null )
{
throw new GameFrameworkException ( "Object is invalid." ) ;
}
return ReleaseObject ( obj . Target ) ;
}
/// <summary>
/// 释放对象。
/// </summary>
/// <param name="target">要释放的对象。</param>
/// <returns>释放对象是否成功。</returns>
public bool ReleaseObject ( object target )
{
if ( target = = null )
{
throw new GameFrameworkException ( "Target is invalid." ) ;
}
Object < T > internalObject = GetObject ( target ) ;
if ( internalObject = = null )
{
return false ;
}
if ( internalObject . IsInUse | | internalObject . Locked | | ! internalObject . CustomCanReleaseFlag )
{
return false ;
}
m_Objects . Remove ( internalObject . Name , internalObject ) ;
m_ObjectMap . Remove ( internalObject . Peek ( ) . Target ) ;
internalObject . Release ( false ) ;
2025-03-20 20:47:11 +08:00
MemoryPool . Release ( internalObject ) ;
2025-02-07 16:04:12 +08:00
return true ;
}
/// <summary>
/// 释放对象池中的可释放对象。
/// </summary>
public override void Release ( )
{
Release ( Count - m_Capacity , m_DefaultReleaseObjectFilterCallback ) ;
}
/// <summary>
/// 释放对象池中的可释放对象。
/// </summary>
/// <param name="toReleaseCount">尝试释放对象数量。</param>
public override void Release ( int toReleaseCount )
{
Release ( toReleaseCount , m_DefaultReleaseObjectFilterCallback ) ;
}
/// <summary>
/// 释放对象池中的可释放对象。
/// </summary>
/// <param name="releaseObjectFilterCallback">释放对象筛选函数。</param>
public void Release ( ReleaseObjectFilterCallback < T > releaseObjectFilterCallback )
{
Release ( Count - m_Capacity , releaseObjectFilterCallback ) ;
}
/// <summary>
/// 释放对象池中的可释放对象。
/// </summary>
/// <param name="toReleaseCount">尝试释放对象数量。</param>
/// <param name="releaseObjectFilterCallback">释放对象筛选函数。</param>
public void Release ( int toReleaseCount , ReleaseObjectFilterCallback < T > releaseObjectFilterCallback )
{
if ( releaseObjectFilterCallback = = null )
{
throw new GameFrameworkException ( "Release object filter callback is invalid." ) ;
}
if ( toReleaseCount < 0 )
{
toReleaseCount = 0 ;
}
DateTime expireTime = DateTime . MinValue ;
if ( m_ExpireTime < float . MaxValue )
{
expireTime = DateTime . UtcNow . AddSeconds ( - m_ExpireTime ) ;
}
m_AutoReleaseTime = 0f ;
GetCanReleaseObjects ( m_CachedCanReleaseObjects ) ;
List < T > toReleaseObjects = releaseObjectFilterCallback ( m_CachedCanReleaseObjects , toReleaseCount , expireTime ) ;
if ( toReleaseObjects = = null | | toReleaseObjects . Count < = 0 )
{
return ;
}
foreach ( T toReleaseObject in toReleaseObjects )
{
ReleaseObject ( toReleaseObject ) ;
}
}
/// <summary>
/// 释放对象池中的所有未使用对象。
/// </summary>
public override void ReleaseAllUnused ( )
{
m_AutoReleaseTime = 0f ;
GetCanReleaseObjects ( m_CachedCanReleaseObjects ) ;
foreach ( T toReleaseObject in m_CachedCanReleaseObjects )
{
ReleaseObject ( toReleaseObject ) ;
}
}
/// <summary>
/// 获取所有对象信息。
/// </summary>
/// <returns>所有对象信息。</returns>
public override ObjectInfo [ ] GetAllObjectInfos ( )
{
List < ObjectInfo > results = new List < ObjectInfo > ( ) ;
foreach ( KeyValuePair < string , GameFrameworkLinkedListRange < Object < T > > > objectRanges in m_Objects )
{
foreach ( Object < T > internalObject in objectRanges . Value )
{
results . Add ( new ObjectInfo ( internalObject . Name , internalObject . Locked , internalObject . CustomCanReleaseFlag , internalObject . Priority , internalObject . LastUseTime , internalObject . SpawnCount ) ) ;
}
}
return results . ToArray ( ) ;
}
internal override void Update ( float elapseSeconds , float realElapseSeconds )
{
m_AutoReleaseTime + = realElapseSeconds ;
if ( m_AutoReleaseTime < m_AutoReleaseInterval )
{
return ;
}
Release ( ) ;
}
internal override void Shutdown ( )
{
foreach ( KeyValuePair < object , Object < T > > objectInMap in m_ObjectMap )
{
objectInMap . Value . Release ( true ) ;
2025-03-20 20:47:11 +08:00
MemoryPool . Release ( objectInMap . Value ) ;
2025-02-07 16:04:12 +08:00
}
m_Objects . Clear ( ) ;
m_ObjectMap . Clear ( ) ;
m_CachedCanReleaseObjects . Clear ( ) ;
m_CachedToReleaseObjects . Clear ( ) ;
}
private Object < T > GetObject ( object target )
{
if ( target = = null )
{
throw new GameFrameworkException ( "Target is invalid." ) ;
}
Object < T > internalObject = null ;
if ( m_ObjectMap . TryGetValue ( target , out internalObject ) )
{
return internalObject ;
}
return null ;
}
private void GetCanReleaseObjects ( List < T > results )
{
if ( results = = null )
{
throw new GameFrameworkException ( "Results is invalid." ) ;
}
results . Clear ( ) ;
foreach ( KeyValuePair < object , Object < T > > objectInMap in m_ObjectMap )
{
Object < T > internalObject = objectInMap . Value ;
if ( internalObject . IsInUse | | internalObject . Locked | | ! internalObject . CustomCanReleaseFlag )
{
continue ;
}
results . Add ( internalObject . Peek ( ) ) ;
}
}
private List < T > DefaultReleaseObjectFilterCallback ( List < T > candidateObjects , int toReleaseCount , DateTime expireTime )
{
m_CachedToReleaseObjects . Clear ( ) ;
if ( expireTime > DateTime . MinValue )
{
for ( int i = candidateObjects . Count - 1 ; i > = 0 ; i - - )
{
if ( candidateObjects [ i ] . LastUseTime < = expireTime )
{
m_CachedToReleaseObjects . Add ( candidateObjects [ i ] ) ;
candidateObjects . RemoveAt ( i ) ;
continue ;
}
}
toReleaseCount - = m_CachedToReleaseObjects . Count ;
}
for ( int i = 0 ; toReleaseCount > 0 & & i < candidateObjects . Count ; i + + )
{
for ( int j = i + 1 ; j < candidateObjects . Count ; j + + )
{
if ( candidateObjects [ i ] . Priority > candidateObjects [ j ] . Priority
| | candidateObjects [ i ] . Priority = = candidateObjects [ j ] . Priority & & candidateObjects [ i ] . LastUseTime > candidateObjects [ j ] . LastUseTime )
{
T temp = candidateObjects [ i ] ;
candidateObjects [ i ] = candidateObjects [ j ] ;
candidateObjects [ j ] = temp ;
}
}
m_CachedToReleaseObjects . Add ( candidateObjects [ i ] ) ;
toReleaseCount - - ;
}
return m_CachedToReleaseObjects ;
}
}
}
2025-03-20 20:47:11 +08:00
}