AlicizaX/Client/Packages/com.alicizax.unity.eventkit/Runtime/Event/EventBase/EventInvokerDataFour.cs
陈思海 eb38f67131 init
2025-01-23 19:06:48 +08:00

186 lines
6.1 KiB
C#

using System;
using System.Buffers;
using System.Runtime.CompilerServices;
using AlicizaX.Runtime;
namespace AlicizaX.EventKit.Runtime
{
/// <summary>
/// 游戏事件数据类。
/// </summary>
public struct EventInvokerData<TArgs1, TArgs2, TArgs3, TArgs4>
{
private readonly string _eventType;
private Action<TArgs1, TArgs2, TArgs3, TArgs4>[] _handlers;
private int _handlerCount;
private Action<TArgs1, TArgs2, TArgs3, TArgs4>[] _addList;
private int _addCount;
private Action<TArgs1, TArgs2, TArgs3, TArgs4>[] _deleteList;
private int _deleteCount;
private bool _isExecute;
private bool _dirty;
private bool _init;
// 使用对象池来管理委托数组
private static readonly ArrayPool<Action<TArgs1, TArgs2, TArgs3, TArgs4>> ActionArrayPool = ArrayPool<Action<TArgs1, TArgs2, TArgs3, TArgs4>>.Shared;
public bool IsEmpty
{
get { return _handlerCount == 0 && !_init; }
}
/// <summary>
/// 构造函数。
/// </summary>
/// <param name="eventType">事件类型。</param>
public EventInvokerData(string eventType)
{
_init = true;
_eventType = eventType;
_handlers = ActionArrayPool.Rent(16); // 预分配16个委托的空间
_handlerCount = 0;
_addList = ActionArrayPool.Rent(4); // 预分配4个
_addCount = 0;
_deleteList = ActionArrayPool.Rent(4); // 预分配4个
_deleteCount = 0;
_isExecute = false;
_dirty = false;
}
/// <summary>
/// 添加注册委托。
/// </summary>
/// <param name="handler">事件处理回调。</param>
/// <returns>是否添加回调成功。</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool AddHandler(Action<TArgs1, TArgs2, TArgs3, TArgs4> handler)
{
if (Array.IndexOf(_handlers, handler, 0, _handlerCount) >= 0)
{
Log.Warning("Repeated Add Handler {0}",handler.Method.Name);
return false;
}
if (_isExecute)
{
EnsureCapacity(ref _addList, ref _addCount);
_addList[_addCount++] = handler;
_dirty = true;
}
else
{
EnsureCapacity(ref _handlers, ref _handlerCount);
_handlers[_handlerCount++] = handler;
}
return true;
}
/// <summary>
/// 移除反注册委托。
/// </summary>
/// <param name="handler">事件处理回调。</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void RemoveHandler(Action<TArgs1, TArgs2, TArgs3, TArgs4> handler)
{
if (_isExecute)
{
EnsureCapacity(ref _deleteList, ref _deleteCount);
_deleteList[_deleteCount++] = handler;
_dirty = true;
}
else
{
int index = Array.IndexOf(_handlers, handler, 0, _handlerCount);
if (index >= 0)
{
_handlers[index] = _handlers[--_handlerCount];
_handlers[_handlerCount] = null; // 避免内存泄漏
}
else
{
Log.Warning("Delete handle failed, not exist, EventId: {0}", _eventType);
}
}
}
/// <summary>
/// 确保数组容量足够,必要时扩容。
/// </summary>
/// <param name="array">数组引用。</param>
/// <param name="count">当前元素数量。</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void EnsureCapacity(ref Action<TArgs1, TArgs2, TArgs3, TArgs4>[] array, ref int count)
{
if (count >= array.Length)
{
var newArray = ActionArrayPool.Rent(array.Length * 2);
Array.Copy(array, newArray, array.Length);
ActionArrayPool.Return(array, clearArray: true);
array = newArray;
}
}
/// <summary>
/// 检测脏数据修正。
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void CheckModify()
{
_isExecute = false;
if (_dirty)
{
for (int i = 0; i < _addCount; i++)
{
EnsureCapacity(ref _handlers, ref _handlerCount);
_handlers[_handlerCount++] = _addList[i];
}
_addCount = 0;
for (int i = 0; i < _deleteCount; i++)
{
int index = Array.IndexOf(_handlers, _deleteList[i], 0, _handlerCount);
if (index >= 0)
{
_handlers[index] = _handlers[--_handlerCount];
_handlers[_handlerCount] = null;
}
}
_deleteCount = 0;
_dirty = false;
}
}
/// <summary>
/// 带参数回调调用。
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Callback(TArgs1 arg1, TArgs2 args2, TArgs3 args3, TArgs4 args4)
{
_isExecute = true;
for (var i = 0; i < _handlerCount; i++)
{
_handlers[i](arg1, args2, args3, args4);
}
CheckModify();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Reset()
{
_init = false;
ActionArrayPool.Return(_handlers, true);
ActionArrayPool.Return(_addList, true);
ActionArrayPool.Return(_deleteList, true);
_handlerCount = 0;
_addCount = 0;
_deleteCount = 0;
_isExecute = false;
_dirty = false;
}
}
}