优化事件系统
This commit is contained in:
parent
69699074de
commit
a1af4b9165
Binary file not shown.
163
Runtime/ABase/Event/EventContainer.cs
Normal file
163
Runtime/ABase/Event/EventContainer.cs
Normal file
@ -0,0 +1,163 @@
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using Unity.IL2CPP.CompilerServices;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AlicizaX
|
||||
{
|
||||
[Il2CppSetOption(Option.NullChecks, false)]
|
||||
[Il2CppSetOption(Option.DivideByZeroChecks, false)]
|
||||
[Il2CppSetOption(Option.ArrayBoundsChecks, false)]
|
||||
public static class EventContainer<TPayload> where TPayload : struct, IEventArgs
|
||||
{
|
||||
private static readonly int InitialSize = EventInitialSize<TPayload>.Size;
|
||||
private static Handler[] _handlers = new Handler[InitialSize];
|
||||
private static int[] _freeSlots = new int[InitialSize];
|
||||
private static int _freeCount = InitialSize;
|
||||
private static int[] _activeIndices = new int[InitialSize];
|
||||
private static int _activeCount;
|
||||
private static int _version;
|
||||
|
||||
#if Event_StrickCheck
|
||||
private static System.Collections.Generic.HashSet<Action<TPayload>> _activeHandlers = new();
|
||||
#endif
|
||||
|
||||
static EventContainer()
|
||||
{
|
||||
Debug.Log(InitialSize);
|
||||
for (int i = 0; i < InitialSize; i++)
|
||||
{
|
||||
_freeSlots[i] = i;
|
||||
}
|
||||
}
|
||||
|
||||
[Il2CppSetOption(Option.NullChecks, false)]
|
||||
[Il2CppSetOption(Option.DivideByZeroChecks, false)]
|
||||
[Il2CppSetOption(Option.ArrayBoundsChecks, false)]
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 4)]
|
||||
private struct Handler
|
||||
{
|
||||
public Action<TPayload> Callback;
|
||||
public int Version;
|
||||
public int ActiveSlot;
|
||||
}
|
||||
|
||||
[Il2CppSetOption(Option.NullChecks, false)]
|
||||
[Il2CppSetOption(Option.DivideByZeroChecks, false)]
|
||||
[Il2CppSetOption(Option.ArrayBoundsChecks, false)]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static EventRuntimeHandle Subscribe(Action<TPayload> callback)
|
||||
{
|
||||
#if Event_StrickCheck
|
||||
if (_activeHandlers.Contains(callback))
|
||||
{
|
||||
Log.Warning($"重复订阅事件处理程序: {callback.Method.Name}");
|
||||
return default;
|
||||
}
|
||||
else
|
||||
{
|
||||
_activeHandlers.Add(callback);
|
||||
}
|
||||
#endif
|
||||
|
||||
int handlerIndex = GetFreeSlot();
|
||||
if (_activeCount >= _activeIndices.Length)
|
||||
{
|
||||
Array.Resize(ref _activeIndices, _activeIndices.Length * 2);
|
||||
}
|
||||
|
||||
int activeIndex = _activeCount++;
|
||||
_activeIndices[activeIndex] = handlerIndex;
|
||||
|
||||
int version = ++_version;
|
||||
_handlers[handlerIndex] = new Handler
|
||||
{
|
||||
Callback = callback,
|
||||
Version = version,
|
||||
ActiveSlot = activeIndex
|
||||
};
|
||||
|
||||
return new EventRuntimeHandle(Unsubscribe, handlerIndex, version);
|
||||
}
|
||||
|
||||
[Il2CppSetOption(Option.NullChecks, false)]
|
||||
[Il2CppSetOption(Option.DivideByZeroChecks, false)]
|
||||
[Il2CppSetOption(Option.ArrayBoundsChecks, false)]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static int GetFreeSlot()
|
||||
{
|
||||
if (_freeCount > 0) return _freeSlots[--_freeCount];
|
||||
|
||||
int oldLen = _handlers.Length;
|
||||
int newSize = oldLen == 0 ? 64 : oldLen * 2;
|
||||
Array.Resize(ref _handlers, newSize);
|
||||
Array.Resize(ref _freeSlots, newSize);
|
||||
|
||||
for (int i = newSize - 1; i >= oldLen; i--)
|
||||
{
|
||||
_freeSlots[_freeCount++] = i;
|
||||
}
|
||||
|
||||
return _freeSlots[--_freeCount];
|
||||
}
|
||||
|
||||
[Il2CppSetOption(Option.NullChecks, false)]
|
||||
[Il2CppSetOption(Option.DivideByZeroChecks, false)]
|
||||
[Il2CppSetOption(Option.ArrayBoundsChecks, false)]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static void Unsubscribe(int handlerIndex, int version)
|
||||
{
|
||||
ref Handler handler = ref _handlers[handlerIndex];
|
||||
if (handler.Version != version) return;
|
||||
|
||||
int lastActiveIndex = --_activeCount;
|
||||
int lastHandlerIndex = _activeIndices[lastActiveIndex];
|
||||
int currentActiveIndex = handler.ActiveSlot;
|
||||
|
||||
_activeIndices[currentActiveIndex] = lastHandlerIndex;
|
||||
_handlers[lastHandlerIndex].ActiveSlot = currentActiveIndex;
|
||||
|
||||
#if Event_StrickCheck
|
||||
_activeHandlers.Remove(handler.Callback);
|
||||
#endif
|
||||
|
||||
handler.Callback = null;
|
||||
handler.Version = 0;
|
||||
|
||||
if (_freeCount >= _freeSlots.Length)
|
||||
{
|
||||
Array.Resize(ref _freeSlots, _freeSlots.Length * 2);
|
||||
}
|
||||
|
||||
_freeSlots[_freeCount++] = handlerIndex;
|
||||
|
||||
}
|
||||
|
||||
|
||||
[Il2CppSetOption(Option.NullChecks, false)]
|
||||
[Il2CppSetOption(Option.DivideByZeroChecks, false)]
|
||||
[Il2CppSetOption(Option.ArrayBoundsChecks, false)]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void Publish(in TPayload payload)
|
||||
{
|
||||
int count = _activeCount;
|
||||
int[] indices = _activeIndices;
|
||||
Handler[] handlers = _handlers;
|
||||
|
||||
int i = 0;
|
||||
for (; i <= count - 4; i += 4)
|
||||
{
|
||||
handlers[indices[i]].Callback(payload);
|
||||
handlers[indices[i + 1]].Callback(payload);
|
||||
handlers[indices[i + 2]].Callback(payload);
|
||||
handlers[indices[i + 3]].Callback(payload);
|
||||
}
|
||||
|
||||
for (; i < count; i++)
|
||||
{
|
||||
handlers[indices[i]].Callback(payload);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Runtime/ABase/Event/EventContainer.cs.meta
Normal file
3
Runtime/ABase/Event/EventContainer.cs.meta
Normal file
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0b7c9a97647245b0a2e0a52e81a466db
|
||||
timeCreated: 1763091204
|
||||
37
Runtime/ABase/Event/EventPublisher.cs
Normal file
37
Runtime/ABase/Event/EventPublisher.cs
Normal file
@ -0,0 +1,37 @@
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Unity.IL2CPP.CompilerServices;
|
||||
|
||||
namespace AlicizaX
|
||||
{
|
||||
public static class EventPublisher
|
||||
{
|
||||
[Il2CppSetOption(Option.NullChecks, false)]
|
||||
[Il2CppSetOption(Option.DivideByZeroChecks, false)]
|
||||
[Il2CppSetOption(Option.ArrayBoundsChecks, false)]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static EventRuntimeHandle Subscribe<T>(Action<T> handler) where T : struct, IEventArgs
|
||||
{
|
||||
return EventContainer<T>.Subscribe(handler);
|
||||
}
|
||||
|
||||
[Il2CppSetOption(Option.NullChecks, false)]
|
||||
[Il2CppSetOption(Option.DivideByZeroChecks, false)]
|
||||
[Il2CppSetOption(Option.ArrayBoundsChecks, false)]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void Publish<T>(in T evt) where T : struct, IEventArgs
|
||||
{
|
||||
EventContainer<T>.Publish(evt);
|
||||
}
|
||||
|
||||
[Il2CppSetOption(Option.NullChecks, false)]
|
||||
[Il2CppSetOption(Option.DivideByZeroChecks, false)]
|
||||
[Il2CppSetOption(Option.ArrayBoundsChecks, false)]
|
||||
public static void Publish<T>(Action<T> init) where T : struct, IEventArgs
|
||||
{
|
||||
var evt = default(T);
|
||||
init(evt);
|
||||
Publish(in evt);
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Runtime/ABase/Event/EventPublisher.cs.meta
Normal file
3
Runtime/ABase/Event/EventPublisher.cs.meta
Normal file
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9376e522d00a4ddab67f7972174e565d
|
||||
timeCreated: 1763091204
|
||||
@ -4,7 +4,6 @@ using Unity.IL2CPP.CompilerServices;
|
||||
|
||||
namespace AlicizaX
|
||||
{
|
||||
public interface IEventArgs { }
|
||||
|
||||
[AttributeUsage(AttributeTargets.Struct)]
|
||||
public sealed class PrewarmAttribute : Attribute
|
||||
|
||||
@ -1,3 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d85feee75c2d4b54bd6b593fe55145d7
|
||||
timeCreated: 1740488369
|
||||
guid: 39414de97b024c4dab09730a52a9de8e
|
||||
timeCreated: 1763091204
|
||||
15
Runtime/ABase/Event/IEventArgs.cs
Normal file
15
Runtime/ABase/Event/IEventArgs.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Unity.IL2CPP.CompilerServices;
|
||||
|
||||
namespace AlicizaX
|
||||
{
|
||||
public interface IEventArgs { }
|
||||
|
||||
public static class EventInitialSize<T> where T : struct, IEventArgs
|
||||
{
|
||||
public static int Size = 4; // default
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
3
Runtime/ABase/Event/IEventArgs.cs.meta
Normal file
3
Runtime/ABase/Event/IEventArgs.cs.meta
Normal file
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 31d1ce58a44948f4811a2e98aac18ec3
|
||||
timeCreated: 1763091204
|
||||
@ -1,2 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 997668ad76a5387428e679240d659155
|
||||
guid: 98d81dd28e344b28aa08c53c92ae6257
|
||||
timeCreated: 1763091204
|
||||
@ -1,4 +1,3 @@
|
||||
using AlicizaX.Framework.Runtime.Event.Generated;
|
||||
|
||||
namespace AlicizaX.Localization
|
||||
{
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Unity.IL2CPP.CompilerServices;
|
||||
|
||||
namespace AlicizaX
|
||||
{
|
||||
@ -10,16 +12,17 @@ namespace AlicizaX
|
||||
{
|
||||
private readonly List<EventRuntimeHandle> _eventHandles = new();
|
||||
|
||||
public EventRuntimeHandle Subscribe
|
||||
|
||||
[Il2CppSetOption(Option.NullChecks, false)]
|
||||
[Il2CppSetOption(Option.DivideByZeroChecks, false)]
|
||||
[Il2CppSetOption(Option.ArrayBoundsChecks, false)]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void AddUIEvent<T>(Action<T> handler) where T : struct, IEventArgs
|
||||
{
|
||||
set => _eventHandles.Add(value);
|
||||
EventRuntimeHandle handle = EventContainer<T>.Subscribe(handler);
|
||||
_eventHandles.Add(handle);
|
||||
}
|
||||
|
||||
public EventListenerProxy Add(EventRuntimeHandle handle)
|
||||
{
|
||||
_eventHandles.Add(handle);
|
||||
return this;
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
@ -27,6 +30,5 @@ namespace AlicizaX
|
||||
_eventHandles[i].Dispose();
|
||||
_eventHandles.Clear();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user