diff --git a/Plugins/EventSourcecGenerator/EventSourceGenerator.dll b/Plugins/EventSourcecGenerator/EventSourceGenerator.dll index 4d79b82..45ce149 100644 Binary files a/Plugins/EventSourcecGenerator/EventSourceGenerator.dll and b/Plugins/EventSourcecGenerator/EventSourceGenerator.dll differ diff --git a/Runtime/ABase/Event/EventContainer.cs b/Runtime/ABase/Event/EventContainer.cs new file mode 100644 index 0000000..845104e --- /dev/null +++ b/Runtime/ABase/Event/EventContainer.cs @@ -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 where TPayload : struct, IEventArgs + { + private static readonly int InitialSize = EventInitialSize.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> _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 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 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); + } + } + } +} diff --git a/Runtime/ABase/Event/EventContainer.cs.meta b/Runtime/ABase/Event/EventContainer.cs.meta new file mode 100644 index 0000000..3639743 --- /dev/null +++ b/Runtime/ABase/Event/EventContainer.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 0b7c9a97647245b0a2e0a52e81a466db +timeCreated: 1763091204 \ No newline at end of file diff --git a/Runtime/ABase/Event/EventPublisher.cs b/Runtime/ABase/Event/EventPublisher.cs new file mode 100644 index 0000000..9ad163f --- /dev/null +++ b/Runtime/ABase/Event/EventPublisher.cs @@ -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(Action handler) where T : struct, IEventArgs + { + return EventContainer.Subscribe(handler); + } + + [Il2CppSetOption(Option.NullChecks, false)] + [Il2CppSetOption(Option.DivideByZeroChecks, false)] + [Il2CppSetOption(Option.ArrayBoundsChecks, false)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void Publish(in T evt) where T : struct, IEventArgs + { + EventContainer.Publish(evt); + } + + [Il2CppSetOption(Option.NullChecks, false)] + [Il2CppSetOption(Option.DivideByZeroChecks, false)] + [Il2CppSetOption(Option.ArrayBoundsChecks, false)] + public static void Publish(Action init) where T : struct, IEventArgs + { + var evt = default(T); + init(evt); + Publish(in evt); + } + } +} \ No newline at end of file diff --git a/Runtime/ABase/Event/EventPublisher.cs.meta b/Runtime/ABase/Event/EventPublisher.cs.meta new file mode 100644 index 0000000..8d84340 --- /dev/null +++ b/Runtime/ABase/Event/EventPublisher.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 9376e522d00a4ddab67f7972174e565d +timeCreated: 1763091204 \ No newline at end of file diff --git a/Runtime/ABase/Event/EventRuntimeHandle.cs b/Runtime/ABase/Event/EventRuntimeHandle.cs index 6438bfe..c5beed1 100644 --- a/Runtime/ABase/Event/EventRuntimeHandle.cs +++ b/Runtime/ABase/Event/EventRuntimeHandle.cs @@ -4,7 +4,6 @@ using Unity.IL2CPP.CompilerServices; namespace AlicizaX { - public interface IEventArgs { } [AttributeUsage(AttributeTargets.Struct)] public sealed class PrewarmAttribute : Attribute diff --git a/Runtime/ABase/Event/EventRuntimeHandle.cs.meta b/Runtime/ABase/Event/EventRuntimeHandle.cs.meta index 6539b7d..4f47c50 100644 --- a/Runtime/ABase/Event/EventRuntimeHandle.cs.meta +++ b/Runtime/ABase/Event/EventRuntimeHandle.cs.meta @@ -1,3 +1,3 @@ fileFormatVersion: 2 -guid: d85feee75c2d4b54bd6b593fe55145d7 -timeCreated: 1740488369 \ No newline at end of file +guid: 39414de97b024c4dab09730a52a9de8e +timeCreated: 1763091204 \ No newline at end of file diff --git a/Runtime/ABase/Event/IEventArgs.cs b/Runtime/ABase/Event/IEventArgs.cs new file mode 100644 index 0000000..6a4d8b1 --- /dev/null +++ b/Runtime/ABase/Event/IEventArgs.cs @@ -0,0 +1,15 @@ +using System; +using System.Runtime.CompilerServices; +using Unity.IL2CPP.CompilerServices; + +namespace AlicizaX +{ + public interface IEventArgs { } + + public static class EventInitialSize where T : struct, IEventArgs + { + public static int Size = 4; // default + } + + +} \ No newline at end of file diff --git a/Runtime/ABase/Event/IEventArgs.cs.meta b/Runtime/ABase/Event/IEventArgs.cs.meta new file mode 100644 index 0000000..75d9b6c --- /dev/null +++ b/Runtime/ABase/Event/IEventArgs.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 31d1ce58a44948f4811a2e98aac18ec3 +timeCreated: 1763091204 \ No newline at end of file diff --git a/Runtime/ABase/Event/Il2CppSetOptionAttribute.cs.meta b/Runtime/ABase/Event/Il2CppSetOptionAttribute.cs.meta index 691658c..c06fc38 100644 --- a/Runtime/ABase/Event/Il2CppSetOptionAttribute.cs.meta +++ b/Runtime/ABase/Event/Il2CppSetOptionAttribute.cs.meta @@ -1,2 +1,3 @@ fileFormatVersion: 2 -guid: 997668ad76a5387428e679240d659155 \ No newline at end of file +guid: 98d81dd28e344b28aa08c53c92ae6257 +timeCreated: 1763091204 \ No newline at end of file diff --git a/Runtime/Localization/Event/LocalizationChangeEvent.cs b/Runtime/Localization/Event/LocalizationChangeEvent.cs index 784c94a..c25e2d5 100644 --- a/Runtime/Localization/Event/LocalizationChangeEvent.cs +++ b/Runtime/Localization/Event/LocalizationChangeEvent.cs @@ -1,4 +1,3 @@ -using AlicizaX.Framework.Runtime.Event.Generated; namespace AlicizaX.Localization { diff --git a/Runtime/UI/EventListenerProxy.cs b/Runtime/UI/EventListenerProxy.cs index f08689d..7131d58 100644 --- a/Runtime/UI/EventListenerProxy.cs +++ b/Runtime/UI/EventListenerProxy.cs @@ -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 _eventHandles = new(); - public EventRuntimeHandle Subscribe + + [Il2CppSetOption(Option.NullChecks, false)] + [Il2CppSetOption(Option.DivideByZeroChecks, false)] + [Il2CppSetOption(Option.ArrayBoundsChecks, false)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void AddUIEvent(Action handler) where T : struct, IEventArgs { - set => _eventHandles.Add(value); + EventRuntimeHandle handle = EventContainer.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(); } - } }