184 lines
5.9 KiB
C#
184 lines
5.9 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>
|
|
{
|
|
private readonly string _eventType;
|
|
private Action<TArgs1, TArgs2, TArgs3>[] _handlers;
|
|
private int _handlerCount;
|
|
private Action<TArgs1, TArgs2, TArgs3>[] _addList;
|
|
private int _addCount;
|
|
private Action<TArgs1, TArgs2, TArgs3>[] _deleteList;
|
|
private int _deleteCount;
|
|
private bool _isExecute;
|
|
private bool _dirty;
|
|
private bool _init;
|
|
|
|
// 使用对象池来管理委托数组
|
|
private static readonly ArrayPool<Action<TArgs1, TArgs2, TArgs3>> ActionArrayPool = ArrayPool<Action<TArgs1, TArgs2, TArgs3>>.Shared;
|
|
|
|
public bool IsEmpty => _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> 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> 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>[] 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)
|
|
{
|
|
_isExecute = true;
|
|
for (var i = 0; i < _handlerCount; i++)
|
|
{
|
|
_handlers[i](arg1, args2, args3);
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|
|
}
|