//------------------------------------------------------------ // Game Framework // Copyright © 2013-2021 loyalsoft. All rights reserved. // Homepage: http://www.game7000.com/ // Feedback: http://www.game7000.com/ //------------------------------------------------------------ using System; using System.Collections.Generic; namespace GameFramework.ObjectPool { internal sealed partial class ObjectPoolManager : GameFrameworkModule, IObjectPoolManager { /// /// 对象池。 /// /// 对象类型。 private sealed class ObjectPool : ObjectPoolBase, IObjectPool where T : ObjectBase { private readonly GameFrameworkMultiDictionary> m_Objects; private readonly Dictionary> m_ObjectMap; private readonly ReleaseObjectFilterCallback m_DefaultReleaseObjectFilterCallback; private readonly List m_CachedCanReleaseObjects; private readonly List 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; /// /// 初始化对象池的新实例。 /// /// 对象池名称。 /// 是否允许对象被多次获取。 /// 对象池自动释放可释放对象的间隔秒数。 /// 对象池的容量。 /// 对象池对象过期秒数。 /// 对象池的优先级。 public ObjectPool(string name, bool allowMultiSpawn, float autoReleaseInterval, int capacity, float expireTime, int priority) : base(name) { m_Objects = new GameFrameworkMultiDictionary>(); m_ObjectMap = new Dictionary>(); m_DefaultReleaseObjectFilterCallback = DefaultReleaseObjectFilterCallback; m_CachedCanReleaseObjects = new List(); m_CachedToReleaseObjects = new List(); m_AllowMultiSpawn = allowMultiSpawn; m_AutoReleaseInterval = autoReleaseInterval; Capacity = capacity; ExpireTime = expireTime; m_Priority = priority; m_AutoReleaseTime = 0f; } /// /// 获取对象池对象类型。 /// public override Type ObjectType { get { return typeof(T); } } /// /// 获取对象池中对象的数量。 /// public override int Count { get { return m_ObjectMap.Count; } } /// /// 获取对象池中能被释放的对象的数量。 /// public override int CanReleaseCount { get { GetCanReleaseObjects(m_CachedCanReleaseObjects); return m_CachedCanReleaseObjects.Count; } } /// /// 获取是否允许对象被多次获取。 /// public override bool AllowMultiSpawn { get { return m_AllowMultiSpawn; } } /// /// 获取或设置对象池自动释放可释放对象的间隔秒数。 /// public override float AutoReleaseInterval { get { return m_AutoReleaseInterval; } set { m_AutoReleaseInterval = value; } } /// /// 获取或设置对象池的容量。 /// 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(); } } /// /// 获取或设置对象池对象过期秒数。 /// 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(); } } /// /// 获取或设置对象池的优先级。 /// public override int Priority { get { return m_Priority; } set { m_Priority = value; } } /// /// 创建对象。 /// /// 对象。 /// 对象是否已被获取。 public void Register(T obj, bool spawned) { if (obj == null) { throw new GameFrameworkException("Object is invalid."); } Object internalObject = Object.Create(obj, spawned); m_Objects.Add(obj.Name, internalObject); m_ObjectMap.Add(obj.Target, internalObject); if (Count > m_Capacity) { Release(); } } /// /// 检查对象。 /// /// 要检查的对象是否存在。 public bool CanSpawn() { return CanSpawn(string.Empty); } /// /// 检查对象。 /// /// 对象名称。 /// 要检查的对象是否存在。 public bool CanSpawn(string name) { if (name == null) { throw new GameFrameworkException("Name is invalid."); } GameFrameworkLinkedListRange> objectRange = default(GameFrameworkLinkedListRange>); if (m_Objects.TryGetValue(name, out objectRange)) { foreach (Object internalObject in objectRange) { if (m_AllowMultiSpawn || !internalObject.IsInUse) { return true; } } } return false; } /// /// 获取对象。 /// /// 要获取的对象。 public T Spawn() { return Spawn(string.Empty); } /// /// 获取对象。 /// /// 对象名称。 /// 要获取的对象。 public T Spawn(string name) { if (name == null) { throw new GameFrameworkException("Name is invalid."); } GameFrameworkLinkedListRange> objectRange = default(GameFrameworkLinkedListRange>); if (m_Objects.TryGetValue(name, out objectRange)) { foreach (Object internalObject in objectRange) { if (m_AllowMultiSpawn || !internalObject.IsInUse) { return internalObject.Spawn(); } } } return null; } /// /// 回收对象。 /// /// 要回收的对象。 public void Unspawn(T obj) { if (obj == null) { throw new GameFrameworkException("Object is invalid."); } Unspawn(obj.Target); } /// /// 回收对象。 /// /// 要回收的对象。 public void Unspawn(object target) { if (target == null) { throw new GameFrameworkException("Target is invalid."); } Object 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)); } } /// /// 设置对象是否被加锁。 /// /// 要设置被加锁的对象。 /// 是否被加锁。 public void SetLocked(T obj, bool locked) { if (obj == null) { throw new GameFrameworkException("Object is invalid."); } SetLocked(obj.Target, locked); } /// /// 设置对象是否被加锁。 /// /// 要设置被加锁的对象。 /// 是否被加锁。 public void SetLocked(object target, bool locked) { if (target == null) { throw new GameFrameworkException("Target is invalid."); } Object 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)); } } /// /// 设置对象的优先级。 /// /// 要设置优先级的对象。 /// 优先级。 public void SetPriority(T obj, int priority) { if (obj == null) { throw new GameFrameworkException("Object is invalid."); } SetPriority(obj.Target, priority); } /// /// 设置对象的优先级。 /// /// 要设置优先级的对象。 /// 优先级。 public void SetPriority(object target, int priority) { if (target == null) { throw new GameFrameworkException("Target is invalid."); } Object 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)); } } /// /// 释放对象。 /// /// 要释放的对象。 /// 释放对象是否成功。 public bool ReleaseObject(T obj) { if (obj == null) { throw new GameFrameworkException("Object is invalid."); } return ReleaseObject(obj.Target); } /// /// 释放对象。 /// /// 要释放的对象。 /// 释放对象是否成功。 public bool ReleaseObject(object target) { if (target == null) { throw new GameFrameworkException("Target is invalid."); } Object 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); ReferencePool.Release(internalObject); return true; } /// /// 释放对象池中的可释放对象。 /// public override void Release() { Release(Count - m_Capacity, m_DefaultReleaseObjectFilterCallback); } /// /// 释放对象池中的可释放对象。 /// /// 尝试释放对象数量。 public override void Release(int toReleaseCount) { Release(toReleaseCount, m_DefaultReleaseObjectFilterCallback); } /// /// 释放对象池中的可释放对象。 /// /// 释放对象筛选函数。 public void Release(ReleaseObjectFilterCallback releaseObjectFilterCallback) { Release(Count - m_Capacity, releaseObjectFilterCallback); } /// /// 释放对象池中的可释放对象。 /// /// 尝试释放对象数量。 /// 释放对象筛选函数。 public void Release(int toReleaseCount, ReleaseObjectFilterCallback 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 toReleaseObjects = releaseObjectFilterCallback(m_CachedCanReleaseObjects, toReleaseCount, expireTime); if (toReleaseObjects == null || toReleaseObjects.Count <= 0) { return; } foreach (T toReleaseObject in toReleaseObjects) { ReleaseObject(toReleaseObject); } } /// /// 释放对象池中的所有未使用对象。 /// public override void ReleaseAllUnused() { m_AutoReleaseTime = 0f; GetCanReleaseObjects(m_CachedCanReleaseObjects); foreach (T toReleaseObject in m_CachedCanReleaseObjects) { ReleaseObject(toReleaseObject); } } /// /// 获取所有对象信息。 /// /// 所有对象信息。 public override ObjectInfo[] GetAllObjectInfos() { List results = new List(); foreach (KeyValuePair>> objectRanges in m_Objects) { foreach (Object 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> objectInMap in m_ObjectMap) { objectInMap.Value.Release(true); ReferencePool.Release(objectInMap.Value); } m_Objects.Clear(); m_ObjectMap.Clear(); m_CachedCanReleaseObjects.Clear(); m_CachedToReleaseObjects.Clear(); } private Object GetObject(object target) { if (target == null) { throw new GameFrameworkException("Target is invalid."); } Object internalObject = null; if (m_ObjectMap.TryGetValue(target, out internalObject)) { return internalObject; } return null; } private void GetCanReleaseObjects(List results) { if (results == null) { throw new GameFrameworkException("Results is invalid."); } results.Clear(); foreach (KeyValuePair> objectInMap in m_ObjectMap) { Object internalObject = objectInMap.Value; if (internalObject.IsInUse || internalObject.Locked || !internalObject.CustomCanReleaseFlag) { continue; } results.Add(internalObject.Peek()); } } private List DefaultReleaseObjectFilterCallback(List 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; } } } }