com.wallstop-studios.dxmessaging 2.2.0 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +315 -67
- package/CHANGELOG.md.meta +7 -7
- package/Editor/Analyzers/BaseCallIlInspector.cs +277 -0
- package/Editor/Analyzers/BaseCallIlInspector.cs.meta +11 -0
- package/Editor/Analyzers/BaseCallLogMessageParser.cs +295 -0
- package/Editor/Analyzers/BaseCallLogMessageParser.cs.meta +11 -0
- package/Editor/Analyzers/BaseCallReportAggregator.cs +308 -0
- package/Editor/Analyzers/BaseCallReportAggregator.cs.meta +11 -0
- package/Editor/Analyzers/BaseCallTypeScanner.cs +110 -0
- package/Editor/Analyzers/BaseCallTypeScanner.cs.meta +11 -0
- package/Editor/Analyzers/BaseCallTypeScannerCore.cs +562 -0
- package/Editor/Analyzers/BaseCallTypeScannerCore.cs.meta +11 -0
- package/Editor/Analyzers/DxMessagingConsoleHarvester.cs +1129 -0
- package/Editor/Analyzers/DxMessagingConsoleHarvester.cs.meta +11 -0
- package/Editor/Analyzers/Microsoft.CodeAnalysis.CSharp.dll.meta +44 -44
- package/Editor/Analyzers/Microsoft.CodeAnalysis.dll.meta +44 -44
- package/Editor/Analyzers/System.Collections.Immutable.dll.meta +44 -44
- package/Editor/Analyzers/System.Reflection.Metadata.dll.meta +44 -44
- package/Editor/Analyzers/System.Runtime.CompilerServices.Unsafe.dll.meta +44 -44
- package/Editor/Analyzers/WallstopStudios.DxMessaging.Analyzer.dll +0 -0
- package/Editor/Analyzers/WallstopStudios.DxMessaging.Analyzer.dll.meta +46 -0
- package/Editor/Analyzers/WallstopStudios.DxMessaging.SourceGenerators.dll +0 -0
- package/Editor/Analyzers/WallstopStudios.DxMessaging.SourceGenerators.dll.meta +72 -72
- package/Editor/Analyzers.meta +8 -8
- package/Editor/AssemblyInfo.cs.meta +11 -3
- package/Editor/CustomEditors/MessageAwareComponentFallbackEditor.cs +81 -0
- package/Editor/CustomEditors/MessageAwareComponentFallbackEditor.cs.meta +11 -0
- package/Editor/CustomEditors/MessageAwareComponentInspectorOverlay.cs +429 -0
- package/Editor/CustomEditors/MessageAwareComponentInspectorOverlay.cs.meta +11 -0
- package/Editor/CustomEditors/MessagingComponentEditor.cs +1 -1
- package/Editor/CustomEditors/MessagingComponentEditor.cs.meta +11 -3
- package/Editor/CustomEditors.meta +2 -2
- package/Editor/DxMessagingEditorIdle.cs +62 -0
- package/Editor/DxMessagingEditorIdle.cs.meta +11 -0
- package/Editor/DxMessagingEditorInitializer.cs +112 -15
- package/Editor/DxMessagingEditorInitializer.cs.meta +11 -3
- package/Editor/DxMessagingEditorLog.cs +32 -0
- package/Editor/DxMessagingEditorLog.cs.meta +11 -0
- package/Editor/DxMessagingMenu.cs.meta +11 -11
- package/Editor/DxMessagingSceneBuildProcessor.cs.meta +11 -11
- package/Editor/Settings/DxMessagingBaseCallIgnoreSync.cs +313 -0
- package/Editor/Settings/DxMessagingBaseCallIgnoreSync.cs.meta +11 -0
- package/Editor/Settings/DxMessagingSettings.cs +261 -11
- package/Editor/Settings/DxMessagingSettings.cs.meta +11 -3
- package/Editor/Settings/DxMessagingSettingsProvider.cs +50 -33
- package/Editor/Settings/DxMessagingSettingsProvider.cs.meta +11 -3
- package/Editor/Settings.meta +2 -2
- package/Editor/SetupCscRsp.cs +406 -39
- package/Editor/SetupCscRsp.cs.meta +11 -3
- package/Editor/Testing/MessagingComponentEditorHarness.cs +2 -2
- package/Editor/Testing/MessagingComponentEditorHarness.cs.meta +11 -3
- package/Editor/Testing.meta +3 -3
- package/Editor/WallstopStudios.DxMessaging.Editor.asmdef +14 -14
- package/Editor/WallstopStudios.DxMessaging.Editor.asmdef.meta +7 -7
- package/Editor.meta +8 -8
- package/LICENSE.md +9 -9
- package/LICENSE.md.meta +7 -7
- package/README.md +940 -900
- package/README.md.meta +7 -7
- package/Runtime/AssemblyInfo.cs +4 -0
- package/Runtime/AssemblyInfo.cs.meta +11 -3
- package/Runtime/Core/Attributes/DxAutoConstructorAttribute.cs.meta +11 -3
- package/Runtime/Core/Attributes/DxBroadcastMessageAttribute.cs.meta +11 -3
- package/Runtime/Core/Attributes/DxIgnoreMissingBaseCallAttribute.cs +26 -0
- package/Runtime/Core/Attributes/DxIgnoreMissingBaseCallAttribute.cs.meta +11 -0
- package/Runtime/Core/Attributes/DxOptionalParameterAttribute.cs +2 -4
- package/Runtime/Core/Attributes/DxOptionalParameterAttribute.cs.meta +11 -3
- package/Runtime/Core/Attributes/DxTargetedMessageAttribute.cs.meta +11 -3
- package/Runtime/Core/Attributes/DxUntargetedMessageAttribute.cs.meta +11 -3
- package/Runtime/Core/Attributes/Il2CppSetOptionAttribute.cs +56 -0
- package/Runtime/Core/Attributes/Il2CppSetOptionAttribute.cs.meta +11 -0
- package/Runtime/Core/Attributes.meta +2 -2
- package/Runtime/Core/Configuration/DxMessagingRuntimeSettings.cs +195 -0
- package/Runtime/Core/Configuration/DxMessagingRuntimeSettings.cs.meta +11 -0
- package/Runtime/Core/Configuration/DxMessagingRuntimeSettingsProvider.cs +179 -0
- package/Runtime/Core/Configuration/DxMessagingRuntimeSettingsProvider.cs.meta +11 -0
- package/Runtime/Core/Configuration.meta +9 -0
- package/Runtime/Core/DataStructure/CyclicBuffer.cs +46 -28
- package/Runtime/Core/DataStructure/CyclicBuffer.cs.meta +11 -3
- package/Runtime/Core/DataStructure.meta +2 -2
- package/Runtime/Core/Diagnostics/MessageEmissionData.cs.meta +11 -3
- package/Runtime/Core/Diagnostics/MessageRegistrationData.cs.meta +11 -3
- package/Runtime/Core/Diagnostics/MessageRegistrationType.cs.meta +11 -3
- package/Runtime/Core/Diagnostics.meta +2 -2
- package/Runtime/Core/DxMessagingStaticState.cs +19 -0
- package/Runtime/Core/DxMessagingStaticState.cs.meta +11 -11
- package/Runtime/Core/Extensions/EnumExtensions.cs +6 -5
- package/Runtime/Core/Extensions/EnumExtensions.cs.meta +11 -3
- package/Runtime/Core/Extensions/IListExtensions.cs.meta +11 -3
- package/Runtime/Core/Extensions/MessageBusExtensions.cs.meta +12 -12
- package/Runtime/Core/Extensions/MessageExtensions.cs +0 -60
- package/Runtime/Core/Extensions/MessageExtensions.cs.meta +11 -11
- package/Runtime/Core/Extensions.meta +8 -8
- package/Runtime/Core/Helper/MessageCache.cs +32 -0
- package/Runtime/Core/Helper/MessageCache.cs.meta +11 -3
- package/Runtime/Core/Helper/MessageHelperIndexer.cs.meta +11 -3
- package/Runtime/Core/Helper.meta +2 -2
- package/Runtime/Core/IMessage.cs +3 -3
- package/Runtime/Core/IMessage.cs.meta +11 -11
- package/Runtime/Core/InstanceId.cs +25 -1
- package/Runtime/Core/InstanceId.cs.meta +11 -11
- package/Runtime/Core/Internal/DxUnsafe.cs +60 -0
- package/Runtime/Core/Internal/DxUnsafe.cs.meta +11 -0
- package/Runtime/Core/Internal/FlatDispatch.cs +198 -0
- package/Runtime/Core/Internal/FlatDispatch.cs.meta +11 -0
- package/Runtime/Core/Internal/TypedGlobalSlotIndex.cs +38 -0
- package/Runtime/Core/Internal/TypedGlobalSlotIndex.cs.meta +11 -0
- package/Runtime/Core/Internal/TypedSlotIndex.cs +81 -0
- package/Runtime/Core/Internal/TypedSlotIndex.cs.meta +11 -0
- package/Runtime/Core/Internal/TypedSlots.cs +597 -0
- package/Runtime/Core/Internal/TypedSlots.cs.meta +11 -0
- package/Runtime/Core/Internal.meta +9 -0
- package/Runtime/Core/MessageBus/DiagnosticsTarget.cs.meta +11 -11
- package/Runtime/Core/MessageBus/GlobalMessageBusProvider.cs.meta +11 -11
- package/Runtime/Core/MessageBus/IMessageBus.cs +189 -15
- package/Runtime/Core/MessageBus/IMessageBus.cs.meta +11 -11
- package/Runtime/Core/MessageBus/IMessageBusProvider.cs.meta +11 -11
- package/Runtime/Core/MessageBus/IMessageRegistrationBuilder.cs +1 -0
- package/Runtime/Core/MessageBus/IMessageRegistrationBuilder.cs.meta +11 -11
- package/Runtime/Core/MessageBus/Internal/BusContextIndex.cs +16 -0
- package/Runtime/Core/MessageBus/Internal/BusContextIndex.cs.meta +11 -0
- package/Runtime/Core/MessageBus/Internal/BusSinkIndex.cs +40 -0
- package/Runtime/Core/MessageBus/Internal/BusSinkIndex.cs.meta +11 -0
- package/Runtime/Core/MessageBus/Internal/BusSlots.cs +719 -0
- package/Runtime/Core/MessageBus/Internal/BusSlots.cs.meta +11 -0
- package/Runtime/Core/MessageBus/Internal/DispatchKind.cs +38 -0
- package/Runtime/Core/MessageBus/Internal/DispatchKind.cs.meta +11 -0
- package/Runtime/Core/MessageBus/Internal/DispatchPhase.cs +20 -0
- package/Runtime/Core/MessageBus/Internal/DispatchPhase.cs.meta +11 -0
- package/Runtime/Core/MessageBus/Internal/DispatchVariant.cs +28 -0
- package/Runtime/Core/MessageBus/Internal/DispatchVariant.cs.meta +11 -0
- package/Runtime/Core/MessageBus/Internal/IEvictableSlot.cs +48 -0
- package/Runtime/Core/MessageBus/Internal/IEvictableSlot.cs.meta +11 -0
- package/Runtime/Core/MessageBus/Internal/ISweepable.cs +15 -0
- package/Runtime/Core/MessageBus/Internal/ISweepable.cs.meta +11 -0
- package/Runtime/Core/MessageBus/Internal/RegistrationMethodAxes.cs +222 -0
- package/Runtime/Core/MessageBus/Internal/RegistrationMethodAxes.cs.meta +11 -0
- package/Runtime/Core/MessageBus/Internal/SlotKey.cs +192 -0
- package/Runtime/Core/MessageBus/Internal/SlotKey.cs.meta +11 -0
- package/Runtime/Core/MessageBus/Internal.meta +9 -0
- package/Runtime/Core/MessageBus/MessageBus.cs +5366 -3838
- package/Runtime/Core/MessageBus/MessageBus.cs.meta +11 -11
- package/Runtime/Core/MessageBus/MessageBusRebindMode.cs.meta +11 -11
- package/Runtime/Core/MessageBus/MessageRegistrationBuilder.cs +187 -14
- package/Runtime/Core/MessageBus/MessageRegistrationBuilder.cs.meta +11 -11
- package/Runtime/Core/MessageBus/MessagingRegistration.cs.meta +11 -11
- package/Runtime/Core/MessageBus/RegistrationLog.cs.meta +11 -11
- package/Runtime/Core/MessageBus.meta +8 -8
- package/Runtime/Core/MessageHandler.cs +2399 -1042
- package/Runtime/Core/MessageHandler.cs.meta +11 -11
- package/Runtime/Core/MessageRegistrationHandle.cs.meta +11 -11
- package/Runtime/Core/MessageRegistrationToken.cs +429 -44
- package/Runtime/Core/MessageRegistrationToken.cs.meta +11 -11
- package/Runtime/Core/Messages/GlobalStringMessage.cs.meta +11 -3
- package/Runtime/Core/Messages/IBroadcastMessage.cs.meta +11 -11
- package/Runtime/Core/Messages/ITargetedMessage.cs.meta +11 -11
- package/Runtime/Core/Messages/IUntargetedMessage.cs.meta +11 -11
- package/Runtime/Core/Messages/ReflexiveMessage.cs.meta +11 -3
- package/Runtime/Core/Messages/SourcedStringMessage.cs.meta +11 -11
- package/Runtime/Core/Messages/StringMessage.cs.meta +11 -3
- package/Runtime/Core/Messages.meta +8 -8
- package/Runtime/Core/MessagingDebug.cs.meta +11 -11
- package/Runtime/Core/Pooling/CollectionPool.cs +266 -0
- package/Runtime/Core/Pooling/CollectionPool.cs.meta +11 -0
- package/Runtime/Core/Pooling/CollectionPoolDiagnostics.cs +30 -0
- package/Runtime/Core/Pooling/CollectionPoolDiagnostics.cs.meta +11 -0
- package/Runtime/Core/Pooling/DxPools.cs +157 -0
- package/Runtime/Core/Pooling/DxPools.cs.meta +11 -0
- package/Runtime/Core/Pooling/EvictionPlayerLoopHook.cs +106 -0
- package/Runtime/Core/Pooling/EvictionPlayerLoopHook.cs.meta +11 -0
- package/Runtime/Core/Pooling/IDxMessagingClock.cs +18 -0
- package/Runtime/Core/Pooling/IDxMessagingClock.cs.meta +11 -0
- package/Runtime/Core/Pooling/PoolDiagnosticsSnapshot.cs +55 -0
- package/Runtime/Core/Pooling/PoolDiagnosticsSnapshot.cs.meta +11 -0
- package/Runtime/Core/Pooling/StopwatchClock.cs +27 -0
- package/Runtime/Core/Pooling/StopwatchClock.cs.meta +11 -0
- package/Runtime/Core/Pooling/UnityRealtimeClock.cs +31 -0
- package/Runtime/Core/Pooling/UnityRealtimeClock.cs.meta +11 -0
- package/Runtime/Core/Pooling.meta +9 -0
- package/Runtime/Core.meta +8 -8
- package/Runtime/Unity/CurrentGlobalMessageBusProvider.cs.meta +12 -12
- package/Runtime/Unity/DxMessagingRuntimeInitializer.cs.meta +11 -11
- package/Runtime/Unity/InitialGlobalMessageBusProvider.cs.meta +12 -12
- package/Runtime/Unity/Integrations/Reflex/AssemblyInfo.cs.meta +11 -3
- package/Runtime/Unity/Integrations/Reflex/ReflexRegistrationInstaller.cs +73 -0
- package/Runtime/Unity/Integrations/Reflex/ReflexRegistrationInstaller.cs.meta +11 -11
- package/Runtime/Unity/Integrations/Reflex/WallstopStudios.DxMessaging.Reflex.asmdef +20 -20
- package/Runtime/Unity/Integrations/Reflex/WallstopStudios.DxMessaging.Reflex.asmdef.meta +7 -7
- package/Runtime/Unity/Integrations/Reflex.meta +8 -8
- package/Runtime/Unity/Integrations/VContainer/AssemblyInfo.cs.meta +11 -3
- package/Runtime/Unity/Integrations/VContainer/VContainerRegistrationExtensions.cs +109 -1
- package/Runtime/Unity/Integrations/VContainer/VContainerRegistrationExtensions.cs.meta +11 -11
- package/Runtime/Unity/Integrations/VContainer/WallstopStudios.DxMessaging.VContainer.asmdef +30 -30
- package/Runtime/Unity/Integrations/VContainer/WallstopStudios.DxMessaging.VContainer.asmdef.meta +7 -7
- package/Runtime/Unity/Integrations/VContainer.meta +8 -8
- package/Runtime/Unity/Integrations/Zenject/AssemblyInfo.cs.meta +11 -3
- package/Runtime/Unity/Integrations/Zenject/WallstopStudios.DxMessaging.Zenject.asmdef +30 -30
- package/Runtime/Unity/Integrations/Zenject/WallstopStudios.DxMessaging.Zenject.asmdef.meta +7 -7
- package/Runtime/Unity/Integrations/Zenject/ZenjectRegistrationInstaller.cs +79 -1
- package/Runtime/Unity/Integrations/Zenject/ZenjectRegistrationInstaller.cs.meta +11 -11
- package/Runtime/Unity/Integrations/Zenject.meta +8 -8
- package/Runtime/Unity/Integrations.meta +8 -8
- package/Runtime/Unity/MessageAwareComponent.cs +74 -0
- package/Runtime/Unity/MessageAwareComponent.cs.meta +11 -11
- package/Runtime/Unity/MessageBusProviderHandle.cs.meta +12 -12
- package/Runtime/Unity/MessagingComponent.cs +43 -10
- package/Runtime/Unity/MessagingComponent.cs.meta +11 -11
- package/Runtime/Unity/MessagingComponentInstaller.cs.meta +12 -12
- package/Runtime/Unity/ScriptableMessageBusProvider.cs.meta +12 -12
- package/Runtime/Unity.meta +8 -8
- package/Runtime/WallstopStudios.DxMessaging.asmdef +14 -14
- package/Runtime/WallstopStudios.DxMessaging.asmdef.meta +7 -7
- package/Runtime.meta +8 -8
- package/Samples~/DI/Prefabs/MessagingInstallerSample.prefab +98 -98
- package/Samples~/DI/Prefabs/MessagingInstallerSample.prefab.meta +7 -7
- package/Samples~/DI/Prefabs.meta +8 -8
- package/Samples~/DI/Providers/GlobalMessageBusProvider.asset +14 -14
- package/Samples~/DI/Providers/GlobalMessageBusProvider.asset.meta +8 -8
- package/Samples~/DI/Providers/InitialGlobalMessageBusProvider.asset +14 -14
- package/Samples~/DI/Providers/InitialGlobalMessageBusProvider.asset.meta +8 -8
- package/Samples~/DI/Providers.meta +8 -8
- package/Samples~/DI/README.md +51 -51
- package/Samples~/DI/README.md.meta +7 -7
- package/Samples~/DI/Reflex/SampleInstaller.cs +7 -0
- package/Samples~/DI/Reflex/SampleInstaller.cs.meta +11 -11
- package/Samples~/DI/Reflex.meta +8 -8
- package/Samples~/DI/VContainer/SampleLifetimeScope.cs +6 -1
- package/Samples~/DI/VContainer/SampleLifetimeScope.cs.meta +11 -11
- package/Samples~/DI/VContainer.meta +8 -8
- package/Samples~/DI/Zenject/SampleInstaller.cs +8 -0
- package/Samples~/DI/Zenject/SampleInstaller.cs.meta +11 -11
- package/Samples~/DI/Zenject.meta +8 -8
- package/Samples~/DI.meta +8 -8
- package/Samples~/Mini Combat/Boot.cs.meta +11 -11
- package/Samples~/Mini Combat/Enemy.cs.meta +11 -11
- package/Samples~/Mini Combat/Messages.cs.meta +11 -11
- package/Samples~/Mini Combat/Player.cs.meta +11 -11
- package/Samples~/Mini Combat/README.md +324 -323
- package/Samples~/Mini Combat/README.md.meta +7 -7
- package/Samples~/Mini Combat/UIOverlay.cs.meta +11 -11
- package/Samples~/Mini Combat/Walkthrough.md +430 -430
- package/Samples~/Mini Combat/Walkthrough.md.meta +7 -7
- package/Samples~/Mini Combat/WallstopStudios.DxMessaging.MiniCombat.Sample.asmdef +13 -13
- package/Samples~/Mini Combat/WallstopStudios.DxMessaging.MiniCombat.Sample.asmdef.meta +7 -7
- package/Samples~/Mini Combat.meta +8 -8
- package/Samples~/UI Buttons + Inspector/DiagnosticsEnabler.cs.meta +11 -11
- package/Samples~/UI Buttons + Inspector/Messages.cs.meta +11 -11
- package/Samples~/UI Buttons + Inspector/MessagingObserver.cs.meta +11 -11
- package/Samples~/UI Buttons + Inspector/README.md +210 -209
- package/Samples~/UI Buttons + Inspector/README.md.meta +7 -7
- package/Samples~/UI Buttons + Inspector/UIButtonEmitter.cs.meta +11 -11
- package/Samples~/UI Buttons + Inspector/WallstopStudios.DxMessaging.UIButtons.Sample.asmdef +13 -13
- package/Samples~/UI Buttons + Inspector/WallstopStudios.DxMessaging.UIButtons.Sample.asmdef.meta +7 -7
- package/Samples~/UI Buttons + Inspector.meta +8 -8
- package/SourceGenerators/Directory.Build.props +50 -3
- package/SourceGenerators/Directory.Build.props.meta +7 -7
- package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/DxAutoConstructorGenerator.cs +96 -63
- package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/DxAutoConstructorGenerator.cs.meta +11 -11
- package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/DxMessageIdGenerator.cs +745 -87
- package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/DxMessageIdGenerator.cs.meta +11 -3
- package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators.csproj +39 -46
- package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators.csproj.meta +7 -7
- package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators.meta +8 -8
- package/SourceGenerators/global.json +7 -0
- package/SourceGenerators/global.json.meta +7 -0
- package/SourceGenerators.meta +8 -8
- package/Third Party Notices.md +3 -3
- package/Third Party Notices.md.meta +7 -7
- package/package.json +102 -92
- package/package.json.meta +7 -7
|
@@ -2,10 +2,13 @@ namespace DxMessaging.Core
|
|
|
2
2
|
{
|
|
3
3
|
using System;
|
|
4
4
|
using System.Collections.Generic;
|
|
5
|
+
using System.Diagnostics;
|
|
5
6
|
using System.Runtime.CompilerServices;
|
|
7
|
+
using DxMessaging.Core.Internal;
|
|
6
8
|
using Helper;
|
|
7
9
|
using MessageBus;
|
|
8
10
|
using Messages;
|
|
11
|
+
using Pooling;
|
|
9
12
|
|
|
10
13
|
/// <summary>
|
|
11
14
|
/// Per-owner handler that executes registered message callbacks.
|
|
@@ -34,302 +37,6 @@ namespace DxMessaging.Core
|
|
|
34
37
|
IComparable,
|
|
35
38
|
IComparable<MessageHandler>
|
|
36
39
|
{
|
|
37
|
-
/// <summary>
|
|
38
|
-
/// Pre-freezes this handler's broadcast post-processor caches for the given message type, source, and priority
|
|
39
|
-
/// for the specified emission id, so registrations during the same emission are not observed.
|
|
40
|
-
/// </summary>
|
|
41
|
-
/// <typeparam name="T">Broadcast message type.</typeparam>
|
|
42
|
-
/// <param name="source">Source instance id.</param>
|
|
43
|
-
/// <param name="priority">Priority bucket to freeze.</param>
|
|
44
|
-
/// <param name="emissionId">Current emission id.</param>
|
|
45
|
-
/// <param name="messageBus">Bus whose typed handler mapping to use.</param>
|
|
46
|
-
internal void PrefreezeBroadcastPostProcessorsForEmission<T>(
|
|
47
|
-
InstanceId source,
|
|
48
|
-
int priority,
|
|
49
|
-
long emissionId,
|
|
50
|
-
IMessageBus messageBus
|
|
51
|
-
)
|
|
52
|
-
where T : IBroadcastMessage
|
|
53
|
-
{
|
|
54
|
-
if (!GetHandlerForType(messageBus, out TypedHandler<T> handler))
|
|
55
|
-
{
|
|
56
|
-
return;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
if (
|
|
60
|
-
handler._broadcastPostProcessingFastHandlers != null
|
|
61
|
-
&& handler._broadcastPostProcessingFastHandlers.TryGetValue(
|
|
62
|
-
source,
|
|
63
|
-
out Dictionary<int, HandlerActionCache<FastHandler<T>>> fastByPriority
|
|
64
|
-
)
|
|
65
|
-
&& fastByPriority.TryGetValue(
|
|
66
|
-
priority,
|
|
67
|
-
out HandlerActionCache<FastHandler<T>> fastCache
|
|
68
|
-
)
|
|
69
|
-
)
|
|
70
|
-
{
|
|
71
|
-
_ = TypedHandler<T>.GetOrAddNewHandlerStack(fastCache, emissionId);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
if (
|
|
75
|
-
handler._broadcastPostProcessingHandlers != null
|
|
76
|
-
&& handler._broadcastPostProcessingHandlers.TryGetValue(
|
|
77
|
-
source,
|
|
78
|
-
out Dictionary<int, HandlerActionCache<Action<T>>> byPriority
|
|
79
|
-
)
|
|
80
|
-
&& byPriority.TryGetValue(priority, out HandlerActionCache<Action<T>> cache)
|
|
81
|
-
)
|
|
82
|
-
{
|
|
83
|
-
_ = TypedHandler<T>.GetOrAddNewHandlerStack(cache, emissionId);
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/// <summary>
|
|
88
|
-
/// Pre-freezes this handler's targeted post-processor caches for the given message type, target, and priority
|
|
89
|
-
/// for the specified emission id, so registrations during the same emission are not observed.
|
|
90
|
-
/// </summary>
|
|
91
|
-
/// <typeparam name="T">Targeted message type.</typeparam>
|
|
92
|
-
/// <param name="target">Target instance id.</param>
|
|
93
|
-
/// <param name="priority">Priority bucket to freeze.</param>
|
|
94
|
-
/// <param name="emissionId">Current emission id.</param>
|
|
95
|
-
/// <param name="messageBus">Bus whose typed handler mapping to use.</param>
|
|
96
|
-
internal void PrefreezeTargetedPostProcessorsForEmission<T>(
|
|
97
|
-
InstanceId target,
|
|
98
|
-
int priority,
|
|
99
|
-
long emissionId,
|
|
100
|
-
IMessageBus messageBus
|
|
101
|
-
)
|
|
102
|
-
where T : ITargetedMessage
|
|
103
|
-
{
|
|
104
|
-
if (!GetHandlerForType(messageBus, out TypedHandler<T> handler))
|
|
105
|
-
{
|
|
106
|
-
return;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
if (
|
|
110
|
-
handler._targetedPostProcessingFastHandlers != null
|
|
111
|
-
&& handler._targetedPostProcessingFastHandlers.TryGetValue(
|
|
112
|
-
target,
|
|
113
|
-
out Dictionary<int, HandlerActionCache<FastHandler<T>>> fastByPriority
|
|
114
|
-
)
|
|
115
|
-
&& fastByPriority.TryGetValue(
|
|
116
|
-
priority,
|
|
117
|
-
out HandlerActionCache<FastHandler<T>> fastCache
|
|
118
|
-
)
|
|
119
|
-
)
|
|
120
|
-
{
|
|
121
|
-
_ = TypedHandler<T>.GetOrAddNewHandlerStack(fastCache, emissionId);
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
if (
|
|
125
|
-
handler._targetedPostProcessingHandlers != null
|
|
126
|
-
&& handler._targetedPostProcessingHandlers.TryGetValue(
|
|
127
|
-
target,
|
|
128
|
-
out Dictionary<int, HandlerActionCache<Action<T>>> byPriority
|
|
129
|
-
)
|
|
130
|
-
&& byPriority.TryGetValue(priority, out HandlerActionCache<Action<T>> cache)
|
|
131
|
-
)
|
|
132
|
-
{
|
|
133
|
-
_ = TypedHandler<T>.GetOrAddNewHandlerStack(cache, emissionId);
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
/// <summary>
|
|
138
|
-
/// Pre-freezes this handler's targeted-without-targeting handler caches for the given message type and priority
|
|
139
|
-
/// so that removals/additions during the same emission are not observed.
|
|
140
|
-
/// </summary>
|
|
141
|
-
internal void PrefreezeTargetedWithoutTargetingHandlersForEmission<T>(
|
|
142
|
-
int priority,
|
|
143
|
-
long emissionId,
|
|
144
|
-
IMessageBus messageBus
|
|
145
|
-
)
|
|
146
|
-
where T : ITargetedMessage
|
|
147
|
-
{
|
|
148
|
-
if (!GetHandlerForType(messageBus, out TypedHandler<T> handler))
|
|
149
|
-
{
|
|
150
|
-
return;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
if (
|
|
154
|
-
handler._fastTargetedWithoutTargetingHandlers != null
|
|
155
|
-
&& handler._fastTargetedWithoutTargetingHandlers.TryGetValue(
|
|
156
|
-
priority,
|
|
157
|
-
out HandlerActionCache<FastHandlerWithContext<T>> fastCache
|
|
158
|
-
)
|
|
159
|
-
)
|
|
160
|
-
{
|
|
161
|
-
_ = TypedHandler<T>.GetOrAddNewHandlerStack(fastCache, emissionId);
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
if (
|
|
165
|
-
handler._targetedWithoutTargetingHandlers != null
|
|
166
|
-
&& handler._targetedWithoutTargetingHandlers.TryGetValue(
|
|
167
|
-
priority,
|
|
168
|
-
out HandlerActionCache<Action<InstanceId, T>> cache
|
|
169
|
-
)
|
|
170
|
-
)
|
|
171
|
-
{
|
|
172
|
-
_ = TypedHandler<T>.GetOrAddNewHandlerStack(cache, emissionId);
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
/// <summary>
|
|
177
|
-
/// Pre-freezes this handler's targeted-without-targeting post-processor caches for a given priority.
|
|
178
|
-
/// </summary>
|
|
179
|
-
internal void PrefreezeTargetedWithoutTargetingPostProcessorsForEmission<T>(
|
|
180
|
-
int priority,
|
|
181
|
-
long emissionId,
|
|
182
|
-
IMessageBus messageBus
|
|
183
|
-
)
|
|
184
|
-
where T : ITargetedMessage
|
|
185
|
-
{
|
|
186
|
-
if (!GetHandlerForType(messageBus, out TypedHandler<T> handler))
|
|
187
|
-
{
|
|
188
|
-
return;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
if (
|
|
192
|
-
handler._fastTargetedWithoutTargetingPostProcessingHandlers != null
|
|
193
|
-
&& handler._fastTargetedWithoutTargetingPostProcessingHandlers.TryGetValue(
|
|
194
|
-
priority,
|
|
195
|
-
out HandlerActionCache<FastHandlerWithContext<T>> fastCache
|
|
196
|
-
)
|
|
197
|
-
)
|
|
198
|
-
{
|
|
199
|
-
_ = TypedHandler<T>.GetOrAddNewHandlerStack(fastCache, emissionId);
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
if (
|
|
203
|
-
handler._targetedWithoutTargetingPostProcessingHandlers != null
|
|
204
|
-
&& handler._targetedWithoutTargetingPostProcessingHandlers.TryGetValue(
|
|
205
|
-
priority,
|
|
206
|
-
out HandlerActionCache<Action<InstanceId, T>> cache
|
|
207
|
-
)
|
|
208
|
-
)
|
|
209
|
-
{
|
|
210
|
-
_ = TypedHandler<T>.GetOrAddNewHandlerStack(cache, emissionId);
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
/// <summary>
|
|
215
|
-
/// Pre-freezes this handler's untargeted post-processor caches for a given priority.
|
|
216
|
-
/// </summary>
|
|
217
|
-
internal void PrefreezeUntargetedPostProcessorsForEmission<T>(
|
|
218
|
-
int priority,
|
|
219
|
-
long emissionId,
|
|
220
|
-
IMessageBus messageBus
|
|
221
|
-
)
|
|
222
|
-
where T : IUntargetedMessage
|
|
223
|
-
{
|
|
224
|
-
if (!GetHandlerForType(messageBus, out TypedHandler<T> handler))
|
|
225
|
-
{
|
|
226
|
-
return;
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
if (
|
|
230
|
-
handler._untargetedPostProcessingFastHandlers != null
|
|
231
|
-
&& handler._untargetedPostProcessingFastHandlers.TryGetValue(
|
|
232
|
-
priority,
|
|
233
|
-
out HandlerActionCache<FastHandler<T>> fastCache
|
|
234
|
-
)
|
|
235
|
-
)
|
|
236
|
-
{
|
|
237
|
-
_ = TypedHandler<T>.GetOrAddNewHandlerStack(fastCache, emissionId);
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
if (
|
|
241
|
-
handler._untargetedPostProcessingHandlers != null
|
|
242
|
-
&& handler._untargetedPostProcessingHandlers.TryGetValue(
|
|
243
|
-
priority,
|
|
244
|
-
out HandlerActionCache<Action<T>> cache
|
|
245
|
-
)
|
|
246
|
-
)
|
|
247
|
-
{
|
|
248
|
-
_ = TypedHandler<T>.GetOrAddNewHandlerStack(cache, emissionId);
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
/// <summary>
|
|
253
|
-
/// Pre-freezes this handler's broadcast-without-source post-processor caches for a given priority.
|
|
254
|
-
/// </summary>
|
|
255
|
-
internal void PrefreezeBroadcastWithoutSourcePostProcessorsForEmission<T>(
|
|
256
|
-
int priority,
|
|
257
|
-
long emissionId,
|
|
258
|
-
IMessageBus messageBus
|
|
259
|
-
)
|
|
260
|
-
where T : IBroadcastMessage
|
|
261
|
-
{
|
|
262
|
-
if (!GetHandlerForType(messageBus, out TypedHandler<T> handler))
|
|
263
|
-
{
|
|
264
|
-
return;
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
if (
|
|
268
|
-
handler._fastBroadcastWithoutSourcePostProcessingHandlers != null
|
|
269
|
-
&& handler._fastBroadcastWithoutSourcePostProcessingHandlers.TryGetValue(
|
|
270
|
-
priority,
|
|
271
|
-
out HandlerActionCache<FastHandlerWithContext<T>> fastCache
|
|
272
|
-
)
|
|
273
|
-
)
|
|
274
|
-
{
|
|
275
|
-
_ = TypedHandler<T>.GetOrAddNewHandlerStack(fastCache, emissionId);
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
if (
|
|
279
|
-
handler._broadcastWithoutSourcePostProcessingHandlers != null
|
|
280
|
-
&& handler._broadcastWithoutSourcePostProcessingHandlers.TryGetValue(
|
|
281
|
-
priority,
|
|
282
|
-
out HandlerActionCache<Action<InstanceId, T>> cache
|
|
283
|
-
)
|
|
284
|
-
)
|
|
285
|
-
{
|
|
286
|
-
_ = TypedHandler<T>.GetOrAddNewHandlerStack(cache, emissionId);
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
/// <summary>
|
|
291
|
-
/// Pre-freezes this handler's broadcast-without-source handler caches for the given message type and priority
|
|
292
|
-
/// for the specified emission id, so removals during the same emission are not observed.
|
|
293
|
-
/// </summary>
|
|
294
|
-
/// <typeparam name="T">Broadcast message type.</typeparam>
|
|
295
|
-
/// <param name="priority">Priority bucket to freeze.</param>
|
|
296
|
-
/// <param name="emissionId">Current emission id.</param>
|
|
297
|
-
/// <param name="messageBus">Bus whose typed handler mapping to use.</param>
|
|
298
|
-
internal void PrefreezeBroadcastWithoutSourceHandlersForEmission<T>(
|
|
299
|
-
int priority,
|
|
300
|
-
long emissionId,
|
|
301
|
-
IMessageBus messageBus
|
|
302
|
-
)
|
|
303
|
-
where T : IBroadcastMessage
|
|
304
|
-
{
|
|
305
|
-
if (!GetHandlerForType(messageBus, out TypedHandler<T> handler))
|
|
306
|
-
{
|
|
307
|
-
return;
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
if (
|
|
311
|
-
handler._fastBroadcastWithoutSourceHandlers != null
|
|
312
|
-
&& handler._fastBroadcastWithoutSourceHandlers.TryGetValue(
|
|
313
|
-
priority,
|
|
314
|
-
out HandlerActionCache<FastHandlerWithContext<T>> fastCache
|
|
315
|
-
)
|
|
316
|
-
)
|
|
317
|
-
{
|
|
318
|
-
_ = TypedHandler<T>.GetOrAddNewHandlerStack(fastCache, emissionId);
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
if (
|
|
322
|
-
handler._broadcastWithoutSourceHandlers != null
|
|
323
|
-
&& handler._broadcastWithoutSourceHandlers.TryGetValue(
|
|
324
|
-
priority,
|
|
325
|
-
out HandlerActionCache<Action<InstanceId, T>> cache
|
|
326
|
-
)
|
|
327
|
-
)
|
|
328
|
-
{
|
|
329
|
-
_ = TypedHandler<T>.GetOrAddNewHandlerStack(cache, emissionId);
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
|
|
333
40
|
/// <summary>
|
|
334
41
|
/// High-performance handler that receives the message by reference (no boxing/copies).
|
|
335
42
|
/// </summary>
|
|
@@ -378,6 +85,19 @@ namespace DxMessaging.Core
|
|
|
378
85
|
ResetStatics();
|
|
379
86
|
}
|
|
380
87
|
|
|
88
|
+
/// <summary>
|
|
89
|
+
/// Reclaims empty slots and pooled collections owned by the current global message bus.
|
|
90
|
+
/// </summary>
|
|
91
|
+
/// <param name="force">
|
|
92
|
+
/// When true, ignores idle-age thresholds and drains shared pools to zero.
|
|
93
|
+
/// When false, only slots past the configured idle threshold are eligible.
|
|
94
|
+
/// </param>
|
|
95
|
+
/// <returns>Counts describing what was reclaimed.</returns>
|
|
96
|
+
public static IMessageBus.TrimResult TrimAll(bool force = false)
|
|
97
|
+
{
|
|
98
|
+
return MessageBus.Trim(force);
|
|
99
|
+
}
|
|
100
|
+
|
|
381
101
|
/// <summary>
|
|
382
102
|
/// Replaces the global <see cref="Core.MessageBus.MessageBus"/> instance returned by <see cref="MessageBus"/>.
|
|
383
103
|
/// </summary>
|
|
@@ -928,19 +648,19 @@ namespace DxMessaging.Core
|
|
|
928
648
|
return;
|
|
929
649
|
}
|
|
930
650
|
|
|
931
|
-
|
|
651
|
+
HandlerActionCache<FastHandler<IUntargetedMessage>> fastCache = handler.GetGlobalCache<
|
|
652
|
+
FastHandler<IUntargetedMessage>
|
|
653
|
+
>(TypedGlobalSlotIndex.UntargetedFast);
|
|
654
|
+
if (fastCache != null)
|
|
932
655
|
{
|
|
933
|
-
_ = TypedHandler<IMessage>.GetOrAddNewHandlerStack(
|
|
934
|
-
handler._globalUntargetedFastHandlers,
|
|
935
|
-
emissionId
|
|
936
|
-
);
|
|
656
|
+
_ = TypedHandler<IMessage>.GetOrAddNewHandlerStack(fastCache, emissionId);
|
|
937
657
|
}
|
|
938
|
-
|
|
658
|
+
HandlerActionCache<Action<IUntargetedMessage>> cache = handler.GetGlobalCache<
|
|
659
|
+
Action<IUntargetedMessage>
|
|
660
|
+
>(TypedGlobalSlotIndex.UntargetedDefault);
|
|
661
|
+
if (cache != null)
|
|
939
662
|
{
|
|
940
|
-
_ = TypedHandler<IMessage>.GetOrAddNewHandlerStack(
|
|
941
|
-
handler._globalUntargetedHandlers,
|
|
942
|
-
emissionId
|
|
943
|
-
);
|
|
663
|
+
_ = TypedHandler<IMessage>.GetOrAddNewHandlerStack(cache, emissionId);
|
|
944
664
|
}
|
|
945
665
|
}
|
|
946
666
|
|
|
@@ -954,19 +674,20 @@ namespace DxMessaging.Core
|
|
|
954
674
|
return;
|
|
955
675
|
}
|
|
956
676
|
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
handler._globalTargetedFastHandlers,
|
|
961
|
-
emissionId
|
|
677
|
+
HandlerActionCache<FastHandlerWithContext<ITargetedMessage>> fastCache =
|
|
678
|
+
handler.GetGlobalCache<FastHandlerWithContext<ITargetedMessage>>(
|
|
679
|
+
TypedGlobalSlotIndex.TargetedFast
|
|
962
680
|
);
|
|
681
|
+
if (fastCache != null)
|
|
682
|
+
{
|
|
683
|
+
_ = TypedHandler<IMessage>.GetOrAddNewHandlerStack(fastCache, emissionId);
|
|
963
684
|
}
|
|
964
|
-
|
|
685
|
+
HandlerActionCache<Action<InstanceId, ITargetedMessage>> cache = handler.GetGlobalCache<
|
|
686
|
+
Action<InstanceId, ITargetedMessage>
|
|
687
|
+
>(TypedGlobalSlotIndex.TargetedDefault);
|
|
688
|
+
if (cache != null)
|
|
965
689
|
{
|
|
966
|
-
_ = TypedHandler<IMessage>.GetOrAddNewHandlerStack(
|
|
967
|
-
handler._globalTargetedHandlers,
|
|
968
|
-
emissionId
|
|
969
|
-
);
|
|
690
|
+
_ = TypedHandler<IMessage>.GetOrAddNewHandlerStack(cache, emissionId);
|
|
970
691
|
}
|
|
971
692
|
}
|
|
972
693
|
|
|
@@ -980,19 +701,21 @@ namespace DxMessaging.Core
|
|
|
980
701
|
return;
|
|
981
702
|
}
|
|
982
703
|
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
handler._globalBroadcastFastHandlers,
|
|
987
|
-
emissionId
|
|
704
|
+
HandlerActionCache<FastHandlerWithContext<IBroadcastMessage>> fastCache =
|
|
705
|
+
handler.GetGlobalCache<FastHandlerWithContext<IBroadcastMessage>>(
|
|
706
|
+
TypedGlobalSlotIndex.BroadcastFast
|
|
988
707
|
);
|
|
989
|
-
|
|
990
|
-
if (handler._globalBroadcastHandlers != null)
|
|
708
|
+
if (fastCache != null)
|
|
991
709
|
{
|
|
992
|
-
_ = TypedHandler<IMessage>.GetOrAddNewHandlerStack(
|
|
993
|
-
|
|
994
|
-
|
|
710
|
+
_ = TypedHandler<IMessage>.GetOrAddNewHandlerStack(fastCache, emissionId);
|
|
711
|
+
}
|
|
712
|
+
HandlerActionCache<Action<InstanceId, IBroadcastMessage>> cache =
|
|
713
|
+
handler.GetGlobalCache<Action<InstanceId, IBroadcastMessage>>(
|
|
714
|
+
TypedGlobalSlotIndex.BroadcastDefault
|
|
995
715
|
);
|
|
716
|
+
if (cache != null)
|
|
717
|
+
{
|
|
718
|
+
_ = TypedHandler<IMessage>.GetOrAddNewHandlerStack(cache, emissionId);
|
|
996
719
|
}
|
|
997
720
|
}
|
|
998
721
|
|
|
@@ -1071,25 +794,28 @@ namespace DxMessaging.Core
|
|
|
1071
794
|
Action untargetedDeregistration = typedHandler.AddGlobalUntargetedHandler(
|
|
1072
795
|
originalUntargetedMessageHandler,
|
|
1073
796
|
untargetedMessageHandler,
|
|
1074
|
-
NullDeregistration
|
|
797
|
+
NullDeregistration,
|
|
798
|
+
messageBus
|
|
1075
799
|
);
|
|
1076
800
|
Action targetedDeregistration = typedHandler.AddGlobalTargetedHandler(
|
|
1077
801
|
originalTargetedMessageHandler,
|
|
1078
802
|
targetedMessageHandler,
|
|
1079
|
-
NullDeregistration
|
|
803
|
+
NullDeregistration,
|
|
804
|
+
messageBus
|
|
1080
805
|
);
|
|
1081
806
|
Action broadcastDeregistration = typedHandler.AddGlobalBroadcastHandler(
|
|
1082
807
|
originalBroadcastMessageHandler,
|
|
1083
808
|
broadcastMessageHandler,
|
|
1084
|
-
NullDeregistration
|
|
809
|
+
NullDeregistration,
|
|
810
|
+
messageBus
|
|
1085
811
|
);
|
|
1086
812
|
|
|
1087
813
|
return () =>
|
|
1088
814
|
{
|
|
815
|
+
messageBusDeregistration?.Invoke();
|
|
1089
816
|
untargetedDeregistration();
|
|
1090
817
|
targetedDeregistration();
|
|
1091
818
|
broadcastDeregistration();
|
|
1092
|
-
messageBusDeregistration?.Invoke();
|
|
1093
819
|
};
|
|
1094
820
|
|
|
1095
821
|
void NullDeregistration()
|
|
@@ -1123,25 +849,28 @@ namespace DxMessaging.Core
|
|
|
1123
849
|
Action untargetedDeregistration = typedHandler.AddGlobalUntargetedHandler(
|
|
1124
850
|
originalUntargetedMessageHandler,
|
|
1125
851
|
untargetedMessageHandler,
|
|
1126
|
-
NullDeregistration
|
|
852
|
+
NullDeregistration,
|
|
853
|
+
messageBus
|
|
1127
854
|
);
|
|
1128
855
|
Action targetedDeregistration = typedHandler.AddGlobalTargetedHandler(
|
|
1129
856
|
originalTargetedMessageHandler,
|
|
1130
857
|
targetedMessageHandler,
|
|
1131
|
-
NullDeregistration
|
|
858
|
+
NullDeregistration,
|
|
859
|
+
messageBus
|
|
1132
860
|
);
|
|
1133
861
|
Action broadcastDeregistration = typedHandler.AddGlobalBroadcastHandler(
|
|
1134
862
|
originalBroadcastMessageHandler,
|
|
1135
863
|
broadcastMessageHandler,
|
|
1136
|
-
NullDeregistration
|
|
864
|
+
NullDeregistration,
|
|
865
|
+
messageBus
|
|
1137
866
|
);
|
|
1138
867
|
|
|
1139
868
|
return () =>
|
|
1140
869
|
{
|
|
870
|
+
messageBusDeregistration?.Invoke();
|
|
1141
871
|
untargetedDeregistration();
|
|
1142
872
|
targetedDeregistration();
|
|
1143
873
|
broadcastDeregistration();
|
|
1144
|
-
messageBusDeregistration?.Invoke();
|
|
1145
874
|
};
|
|
1146
875
|
|
|
1147
876
|
void NullDeregistration()
|
|
@@ -1181,7 +910,7 @@ namespace DxMessaging.Core
|
|
|
1181
910
|
messageHandler,
|
|
1182
911
|
messageBusDeregistration,
|
|
1183
912
|
priority,
|
|
1184
|
-
messageBus
|
|
913
|
+
messageBus
|
|
1185
914
|
);
|
|
1186
915
|
}
|
|
1187
916
|
|
|
@@ -1216,7 +945,7 @@ namespace DxMessaging.Core
|
|
|
1216
945
|
messageHandler,
|
|
1217
946
|
messageBusDeregistration,
|
|
1218
947
|
priority,
|
|
1219
|
-
messageBus
|
|
948
|
+
messageBus
|
|
1220
949
|
);
|
|
1221
950
|
}
|
|
1222
951
|
|
|
@@ -1251,7 +980,7 @@ namespace DxMessaging.Core
|
|
|
1251
980
|
messageHandler,
|
|
1252
981
|
messageBusDeregistration,
|
|
1253
982
|
priority,
|
|
1254
|
-
messageBus
|
|
983
|
+
messageBus
|
|
1255
984
|
);
|
|
1256
985
|
}
|
|
1257
986
|
|
|
@@ -1286,7 +1015,7 @@ namespace DxMessaging.Core
|
|
|
1286
1015
|
messageHandler,
|
|
1287
1016
|
messageBusDeregistration,
|
|
1288
1017
|
priority,
|
|
1289
|
-
messageBus
|
|
1018
|
+
messageBus
|
|
1290
1019
|
);
|
|
1291
1020
|
}
|
|
1292
1021
|
|
|
@@ -1318,7 +1047,7 @@ namespace DxMessaging.Core
|
|
|
1318
1047
|
messageHandler,
|
|
1319
1048
|
messageBusDeregistration,
|
|
1320
1049
|
priority,
|
|
1321
|
-
messageBus
|
|
1050
|
+
messageBus
|
|
1322
1051
|
);
|
|
1323
1052
|
}
|
|
1324
1053
|
|
|
@@ -1350,7 +1079,7 @@ namespace DxMessaging.Core
|
|
|
1350
1079
|
messageHandler,
|
|
1351
1080
|
messageBusDeregistration,
|
|
1352
1081
|
priority,
|
|
1353
|
-
messageBus
|
|
1082
|
+
messageBus
|
|
1354
1083
|
);
|
|
1355
1084
|
}
|
|
1356
1085
|
|
|
@@ -1381,7 +1110,7 @@ namespace DxMessaging.Core
|
|
|
1381
1110
|
messageHandler,
|
|
1382
1111
|
messageBusDeregistration,
|
|
1383
1112
|
priority,
|
|
1384
|
-
messageBus
|
|
1113
|
+
messageBus
|
|
1385
1114
|
);
|
|
1386
1115
|
}
|
|
1387
1116
|
|
|
@@ -1412,7 +1141,7 @@ namespace DxMessaging.Core
|
|
|
1412
1141
|
messageHandler,
|
|
1413
1142
|
messageBusDeregistration,
|
|
1414
1143
|
priority,
|
|
1415
|
-
messageBus
|
|
1144
|
+
messageBus
|
|
1416
1145
|
);
|
|
1417
1146
|
}
|
|
1418
1147
|
|
|
@@ -1443,7 +1172,7 @@ namespace DxMessaging.Core
|
|
|
1443
1172
|
messageHandler,
|
|
1444
1173
|
messageBusDeregistration,
|
|
1445
1174
|
priority,
|
|
1446
|
-
messageBus
|
|
1175
|
+
messageBus
|
|
1447
1176
|
);
|
|
1448
1177
|
}
|
|
1449
1178
|
|
|
@@ -1474,7 +1203,7 @@ namespace DxMessaging.Core
|
|
|
1474
1203
|
messageHandler,
|
|
1475
1204
|
messageBusDeregistration,
|
|
1476
1205
|
priority,
|
|
1477
|
-
messageBus
|
|
1206
|
+
messageBus
|
|
1478
1207
|
);
|
|
1479
1208
|
}
|
|
1480
1209
|
|
|
@@ -1505,7 +1234,7 @@ namespace DxMessaging.Core
|
|
|
1505
1234
|
messageHandler,
|
|
1506
1235
|
messageBusDeregistration,
|
|
1507
1236
|
priority,
|
|
1508
|
-
messageBus
|
|
1237
|
+
messageBus
|
|
1509
1238
|
);
|
|
1510
1239
|
}
|
|
1511
1240
|
|
|
@@ -1536,7 +1265,7 @@ namespace DxMessaging.Core
|
|
|
1536
1265
|
messageHandler,
|
|
1537
1266
|
messageBusDeregistration,
|
|
1538
1267
|
priority,
|
|
1539
|
-
messageBus
|
|
1268
|
+
messageBus
|
|
1540
1269
|
);
|
|
1541
1270
|
}
|
|
1542
1271
|
|
|
@@ -1572,7 +1301,7 @@ namespace DxMessaging.Core
|
|
|
1572
1301
|
messageHandler,
|
|
1573
1302
|
messageBusDeregistration,
|
|
1574
1303
|
priority,
|
|
1575
|
-
messageBus
|
|
1304
|
+
messageBus
|
|
1576
1305
|
);
|
|
1577
1306
|
}
|
|
1578
1307
|
|
|
@@ -1607,7 +1336,7 @@ namespace DxMessaging.Core
|
|
|
1607
1336
|
messageHandler,
|
|
1608
1337
|
messageBusDeregistration,
|
|
1609
1338
|
priority,
|
|
1610
|
-
messageBus
|
|
1339
|
+
messageBus
|
|
1611
1340
|
);
|
|
1612
1341
|
}
|
|
1613
1342
|
|
|
@@ -1638,7 +1367,7 @@ namespace DxMessaging.Core
|
|
|
1638
1367
|
messageHandler,
|
|
1639
1368
|
messageBusDeregistration,
|
|
1640
1369
|
priority,
|
|
1641
|
-
messageBus
|
|
1370
|
+
messageBus
|
|
1642
1371
|
);
|
|
1643
1372
|
}
|
|
1644
1373
|
|
|
@@ -1669,7 +1398,7 @@ namespace DxMessaging.Core
|
|
|
1669
1398
|
messageHandler,
|
|
1670
1399
|
messageBusDeregistration,
|
|
1671
1400
|
priority,
|
|
1672
|
-
messageBus
|
|
1401
|
+
messageBus
|
|
1673
1402
|
);
|
|
1674
1403
|
}
|
|
1675
1404
|
|
|
@@ -1704,7 +1433,7 @@ namespace DxMessaging.Core
|
|
|
1704
1433
|
messageHandler,
|
|
1705
1434
|
messageBusDeregistration,
|
|
1706
1435
|
priority,
|
|
1707
|
-
messageBus
|
|
1436
|
+
messageBus
|
|
1708
1437
|
);
|
|
1709
1438
|
}
|
|
1710
1439
|
|
|
@@ -1739,7 +1468,7 @@ namespace DxMessaging.Core
|
|
|
1739
1468
|
messageHandler,
|
|
1740
1469
|
messageBusDeregistration,
|
|
1741
1470
|
priority,
|
|
1742
|
-
messageBus
|
|
1471
|
+
messageBus
|
|
1743
1472
|
);
|
|
1744
1473
|
}
|
|
1745
1474
|
|
|
@@ -1771,7 +1500,7 @@ namespace DxMessaging.Core
|
|
|
1771
1500
|
messageHandler,
|
|
1772
1501
|
messageBusDeregistration,
|
|
1773
1502
|
priority,
|
|
1774
|
-
messageBus
|
|
1503
|
+
messageBus
|
|
1775
1504
|
);
|
|
1776
1505
|
}
|
|
1777
1506
|
|
|
@@ -1803,7 +1532,7 @@ namespace DxMessaging.Core
|
|
|
1803
1532
|
messageHandler,
|
|
1804
1533
|
messageBusDeregistration,
|
|
1805
1534
|
priority,
|
|
1806
|
-
messageBus
|
|
1535
|
+
messageBus
|
|
1807
1536
|
);
|
|
1808
1537
|
}
|
|
1809
1538
|
|
|
@@ -1956,7 +1685,7 @@ namespace DxMessaging.Core
|
|
|
1956
1685
|
MessageCache<object> handlersByType = _handlersByTypeByMessageBus[messageBusIndex];
|
|
1957
1686
|
if (handlersByType.TryGetValue<T>(out object untypedHandler))
|
|
1958
1687
|
{
|
|
1959
|
-
return
|
|
1688
|
+
return DxUnsafe.As<TypedHandler<T>>(untypedHandler);
|
|
1960
1689
|
}
|
|
1961
1690
|
|
|
1962
1691
|
TypedHandler<T> typedHandler = new();
|
|
@@ -1988,7 +1717,7 @@ namespace DxMessaging.Core
|
|
|
1988
1717
|
.TryGetValue<T>(out object untypedHandler)
|
|
1989
1718
|
)
|
|
1990
1719
|
{
|
|
1991
|
-
existingTypedHandler =
|
|
1720
|
+
existingTypedHandler = DxUnsafe.As<TypedHandler<T>>(untypedHandler);
|
|
1992
1721
|
return true;
|
|
1993
1722
|
}
|
|
1994
1723
|
|
|
@@ -1996,675 +1725,931 @@ namespace DxMessaging.Core
|
|
|
1996
1725
|
return false;
|
|
1997
1726
|
}
|
|
1998
1727
|
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
1728
|
+
/// <summary>
|
|
1729
|
+
/// Resets empty typed-handler slots associated with
|
|
1730
|
+
/// <paramref name="messageBus"/>. The eviction layer calls through
|
|
1731
|
+
/// this erased surface after bus-side slots prove idle and empty.
|
|
1732
|
+
/// </summary>
|
|
1733
|
+
/// <param name="messageBus">
|
|
1734
|
+
/// Bus whose typed-handler cache should be swept. Null resolves to
|
|
1735
|
+
/// this handler's default bus.
|
|
1736
|
+
/// </param>
|
|
1737
|
+
/// <returns>Number of typed or typed-global slots reset.</returns>
|
|
1738
|
+
internal int ResetEmptyTypedSlotsForSweep(IMessageBus messageBus = null)
|
|
2004
1739
|
{
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
)
|
|
1740
|
+
messageBus = ResolveMessageBus(messageBus);
|
|
1741
|
+
int messageBusIndex = messageBus.RegisteredGlobalSequentialIndex;
|
|
1742
|
+
if (messageBusIndex < 0 || _handlersByTypeByMessageBus.Count <= messageBusIndex)
|
|
2009
1743
|
{
|
|
2010
1744
|
return 0;
|
|
2011
1745
|
}
|
|
2012
1746
|
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
out HandlerActionCache<FastHandler<T>> cache
|
|
2017
|
-
)
|
|
2018
|
-
)
|
|
1747
|
+
int resetCount = 0;
|
|
1748
|
+
MessageCache<object> handlersByType = _handlersByTypeByMessageBus[messageBusIndex];
|
|
1749
|
+
foreach (object untypedHandler in _handlersByTypeByMessageBus[messageBusIndex])
|
|
2019
1750
|
{
|
|
2020
|
-
|
|
1751
|
+
if (untypedHandler is ITypedHandlerSlotSweeper sweeper)
|
|
1752
|
+
{
|
|
1753
|
+
resetCount += sweeper.ResetEmptySlotsForSweep();
|
|
1754
|
+
if (sweeper.MarkedForOuterRemoval)
|
|
1755
|
+
{
|
|
1756
|
+
handlersByType.RemoveAtIndex(sweeper.MessageTypeIndex);
|
|
1757
|
+
}
|
|
1758
|
+
}
|
|
2021
1759
|
}
|
|
2022
1760
|
|
|
2023
|
-
return
|
|
1761
|
+
return resetCount;
|
|
2024
1762
|
}
|
|
2025
1763
|
|
|
2026
|
-
|
|
2027
|
-
internal UntargetedDispatchLink<T> GetOrCreateUntargetedDispatchLink<T>(
|
|
2028
|
-
IMessageBus messageBus
|
|
2029
|
-
)
|
|
2030
|
-
where T : IMessage
|
|
1764
|
+
internal int ResetAllTypedSlotsForBusReset(IMessageBus messageBus = null)
|
|
2031
1765
|
{
|
|
2032
|
-
|
|
2033
|
-
|
|
1766
|
+
messageBus = ResolveMessageBus(messageBus);
|
|
1767
|
+
int messageBusIndex = messageBus.RegisteredGlobalSequentialIndex;
|
|
1768
|
+
if (messageBusIndex < 0 || _handlersByTypeByMessageBus.Count <= messageBusIndex)
|
|
1769
|
+
{
|
|
1770
|
+
return 0;
|
|
1771
|
+
}
|
|
1772
|
+
|
|
1773
|
+
int resetCount = 0;
|
|
1774
|
+
foreach (object untypedHandler in _handlersByTypeByMessageBus[messageBusIndex])
|
|
1775
|
+
{
|
|
1776
|
+
if (untypedHandler is ITypedHandlerSlotSweeper sweeper)
|
|
1777
|
+
{
|
|
1778
|
+
resetCount += sweeper.ResetAllSlotsForBusReset();
|
|
1779
|
+
}
|
|
1780
|
+
}
|
|
1781
|
+
|
|
1782
|
+
return resetCount;
|
|
2034
1783
|
}
|
|
2035
1784
|
|
|
2036
|
-
|
|
2037
|
-
internal UntargetedPostDispatchLink<T> GetOrCreateUntargetedPostDispatchLink<T>(
|
|
2038
|
-
IMessageBus messageBus
|
|
2039
|
-
)
|
|
2040
|
-
where T : IMessage
|
|
1785
|
+
internal int CountEmptyTypedSlotsForSweep(IMessageBus messageBus = null)
|
|
2041
1786
|
{
|
|
2042
|
-
|
|
2043
|
-
|
|
1787
|
+
messageBus = ResolveMessageBus(messageBus);
|
|
1788
|
+
int messageBusIndex = messageBus.RegisteredGlobalSequentialIndex;
|
|
1789
|
+
if (messageBusIndex < 0 || _handlersByTypeByMessageBus.Count <= messageBusIndex)
|
|
1790
|
+
{
|
|
1791
|
+
return 0;
|
|
1792
|
+
}
|
|
1793
|
+
|
|
1794
|
+
int count = 0;
|
|
1795
|
+
foreach (object untypedHandler in _handlersByTypeByMessageBus[messageBusIndex])
|
|
1796
|
+
{
|
|
1797
|
+
if (untypedHandler is ITypedHandlerSlotSweeper sweeper)
|
|
1798
|
+
{
|
|
1799
|
+
count += sweeper.CountEmptySlotsForSweep();
|
|
1800
|
+
}
|
|
1801
|
+
}
|
|
1802
|
+
|
|
1803
|
+
return count;
|
|
2044
1804
|
}
|
|
2045
1805
|
|
|
2046
|
-
|
|
2047
|
-
internal TargetedDispatchLink<T> GetOrCreateTargetedDispatchLink<T>(IMessageBus messageBus)
|
|
2048
|
-
where T : IMessage
|
|
1806
|
+
internal bool HasTypedHandlersForBus(IMessageBus messageBus = null)
|
|
2049
1807
|
{
|
|
2050
|
-
|
|
2051
|
-
|
|
1808
|
+
messageBus = ResolveMessageBus(messageBus);
|
|
1809
|
+
int messageBusIndex = messageBus.RegisteredGlobalSequentialIndex;
|
|
1810
|
+
if (messageBusIndex < 0 || _handlersByTypeByMessageBus.Count <= messageBusIndex)
|
|
1811
|
+
{
|
|
1812
|
+
return false;
|
|
1813
|
+
}
|
|
1814
|
+
|
|
1815
|
+
foreach (object untypedHandler in _handlersByTypeByMessageBus[messageBusIndex])
|
|
1816
|
+
{
|
|
1817
|
+
if (untypedHandler != null)
|
|
1818
|
+
{
|
|
1819
|
+
return true;
|
|
1820
|
+
}
|
|
1821
|
+
}
|
|
1822
|
+
|
|
1823
|
+
return false;
|
|
2052
1824
|
}
|
|
2053
1825
|
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
1826
|
+
/// <summary>
|
|
1827
|
+
/// Counts the flat-dispatch entries this handler contributes to a
|
|
1828
|
+
/// non-context-keyed slot (untargeted handle/post) at the given
|
|
1829
|
+
/// priority: one entry per unique registered delegate (fast plus
|
|
1830
|
+
/// default). Build-time only; called by MessageBus.BuildFlatDispatch.
|
|
1831
|
+
/// </summary>
|
|
1832
|
+
internal int CountFlatHandlers<T>(
|
|
1833
|
+
IMessageBus messageBus,
|
|
1834
|
+
int priority,
|
|
1835
|
+
int fastIndex,
|
|
1836
|
+
int defaultIndex
|
|
2057
1837
|
)
|
|
2058
1838
|
where T : IMessage
|
|
2059
1839
|
{
|
|
2060
|
-
TypedHandler<T> typedHandler
|
|
2061
|
-
|
|
1840
|
+
if (!GetHandlerForType(messageBus, out TypedHandler<T> typedHandler))
|
|
1841
|
+
{
|
|
1842
|
+
return 0;
|
|
1843
|
+
}
|
|
1844
|
+
|
|
1845
|
+
return CountFlatDelegates<FastHandler<T>>(
|
|
1846
|
+
typedHandler.GetPriorityHandlers(fastIndex),
|
|
1847
|
+
priority
|
|
1848
|
+
)
|
|
1849
|
+
+ CountFlatDelegates<Action<T>>(
|
|
1850
|
+
typedHandler.GetPriorityHandlers(defaultIndex),
|
|
1851
|
+
priority
|
|
1852
|
+
);
|
|
2062
1853
|
}
|
|
2063
1854
|
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
1855
|
+
/// <summary>
|
|
1856
|
+
/// Counts the flat-dispatch entries this handler contributes to a
|
|
1857
|
+
/// context-keyed slot (Default-variant targeted/broadcast handle/post)
|
|
1858
|
+
/// for the given context and priority. Build-time only.
|
|
1859
|
+
/// </summary>
|
|
1860
|
+
internal int CountContextFlatHandlers<T>(
|
|
1861
|
+
IMessageBus messageBus,
|
|
1862
|
+
InstanceId context,
|
|
1863
|
+
int priority,
|
|
1864
|
+
int fastIndex,
|
|
1865
|
+
int defaultIndex
|
|
2067
1866
|
)
|
|
2068
1867
|
where T : IMessage
|
|
2069
1868
|
{
|
|
2070
|
-
TypedHandler<T> typedHandler
|
|
2071
|
-
|
|
1869
|
+
if (!GetHandlerForType(messageBus, out TypedHandler<T> typedHandler))
|
|
1870
|
+
{
|
|
1871
|
+
return 0;
|
|
1872
|
+
}
|
|
1873
|
+
|
|
1874
|
+
return CountFlatDelegates<FastHandler<T>>(
|
|
1875
|
+
GetContextPriorityHandlers(typedHandler, fastIndex, context),
|
|
1876
|
+
priority
|
|
1877
|
+
)
|
|
1878
|
+
+ CountFlatDelegates<Action<T>>(
|
|
1879
|
+
GetContextPriorityHandlers(typedHandler, defaultIndex, context),
|
|
1880
|
+
priority
|
|
1881
|
+
);
|
|
2072
1882
|
}
|
|
2073
1883
|
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
1884
|
+
/// <summary>
|
|
1885
|
+
/// Counts the flat-dispatch entries this handler contributes to a
|
|
1886
|
+
/// WithoutContext targeted/broadcast slot (whose delegates receive the
|
|
1887
|
+
/// routing InstanceId) at the given priority. Build-time only.
|
|
1888
|
+
/// </summary>
|
|
1889
|
+
internal int CountWithContextFlatHandlers<T>(
|
|
1890
|
+
IMessageBus messageBus,
|
|
1891
|
+
int priority,
|
|
1892
|
+
int fastIndex,
|
|
1893
|
+
int defaultIndex
|
|
2077
1894
|
)
|
|
2078
1895
|
where T : IMessage
|
|
2079
1896
|
{
|
|
2080
|
-
TypedHandler<T> typedHandler
|
|
2081
|
-
|
|
1897
|
+
if (!GetHandlerForType(messageBus, out TypedHandler<T> typedHandler))
|
|
1898
|
+
{
|
|
1899
|
+
return 0;
|
|
1900
|
+
}
|
|
1901
|
+
|
|
1902
|
+
return CountFlatDelegates<FastHandlerWithContext<T>>(
|
|
1903
|
+
typedHandler.GetPriorityHandlers(fastIndex),
|
|
1904
|
+
priority
|
|
1905
|
+
)
|
|
1906
|
+
+ CountFlatDelegates<Action<InstanceId, T>>(
|
|
1907
|
+
typedHandler.GetPriorityHandlers(defaultIndex),
|
|
1908
|
+
priority
|
|
1909
|
+
);
|
|
2082
1910
|
}
|
|
2083
1911
|
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
1912
|
+
/// <summary>
|
|
1913
|
+
/// Writes this handler's resolved flat-dispatch entries for a
|
|
1914
|
+
/// non-context-keyed FastHandler-shaped slot into
|
|
1915
|
+
/// <paramref name="target"/> starting at <paramref name="writeIndex"/>:
|
|
1916
|
+
/// all fast entries in registration order, then all default entries in
|
|
1917
|
+
/// registration order, matching the legacy link path's
|
|
1918
|
+
/// fast-before-default contract. Fast entries resolve to the augmented
|
|
1919
|
+
/// FastHandler delegate itself; default entries resolve to the
|
|
1920
|
+
/// FastHandler adapter created at registration time
|
|
1921
|
+
/// (Entry.flatInvoker), so this method allocates nothing.
|
|
1922
|
+
/// Returns the next write index.
|
|
1923
|
+
/// </summary>
|
|
1924
|
+
internal int FillFlatHandlers<T>(
|
|
1925
|
+
IMessageBus messageBus,
|
|
1926
|
+
int priority,
|
|
1927
|
+
int fastIndex,
|
|
1928
|
+
int defaultIndex,
|
|
1929
|
+
FlatDispatchEntry<T>[] target,
|
|
1930
|
+
int writeIndex
|
|
2087
1931
|
)
|
|
2088
1932
|
where T : IMessage
|
|
2089
1933
|
{
|
|
2090
|
-
TypedHandler<T> typedHandler
|
|
2091
|
-
|
|
1934
|
+
if (!GetHandlerForType(messageBus, out TypedHandler<T> typedHandler))
|
|
1935
|
+
{
|
|
1936
|
+
return writeIndex;
|
|
1937
|
+
}
|
|
1938
|
+
|
|
1939
|
+
writeIndex = FillFastFlatEntries(
|
|
1940
|
+
typedHandler.GetPriorityHandlers(fastIndex),
|
|
1941
|
+
priority,
|
|
1942
|
+
target,
|
|
1943
|
+
writeIndex
|
|
1944
|
+
);
|
|
1945
|
+
return FillDefaultFlatEntries(
|
|
1946
|
+
typedHandler.GetPriorityHandlers(defaultIndex),
|
|
1947
|
+
priority,
|
|
1948
|
+
target,
|
|
1949
|
+
writeIndex
|
|
1950
|
+
);
|
|
2092
1951
|
}
|
|
2093
1952
|
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
1953
|
+
/// <summary>
|
|
1954
|
+
/// Context-keyed sibling of <see cref="FillFlatHandlers{T}"/> for the
|
|
1955
|
+
/// Default-variant targeted/broadcast slots: resolves the per-context
|
|
1956
|
+
/// priority map first, then fills fast entries followed by default
|
|
1957
|
+
/// entries in registration order. Returns the next write index.
|
|
1958
|
+
/// </summary>
|
|
1959
|
+
internal int FillContextFlatHandlers<T>(
|
|
1960
|
+
IMessageBus messageBus,
|
|
1961
|
+
InstanceId context,
|
|
1962
|
+
int priority,
|
|
1963
|
+
int fastIndex,
|
|
1964
|
+
int defaultIndex,
|
|
1965
|
+
FlatDispatchEntry<T>[] target,
|
|
1966
|
+
int writeIndex
|
|
2097
1967
|
)
|
|
2098
1968
|
where T : IMessage
|
|
2099
1969
|
{
|
|
2100
|
-
TypedHandler<T> typedHandler
|
|
2101
|
-
|
|
1970
|
+
if (!GetHandlerForType(messageBus, out TypedHandler<T> typedHandler))
|
|
1971
|
+
{
|
|
1972
|
+
return writeIndex;
|
|
1973
|
+
}
|
|
1974
|
+
|
|
1975
|
+
writeIndex = FillFastFlatEntries(
|
|
1976
|
+
GetContextPriorityHandlers(typedHandler, fastIndex, context),
|
|
1977
|
+
priority,
|
|
1978
|
+
target,
|
|
1979
|
+
writeIndex
|
|
1980
|
+
);
|
|
1981
|
+
return FillDefaultFlatEntries(
|
|
1982
|
+
GetContextPriorityHandlers(typedHandler, defaultIndex, context),
|
|
1983
|
+
priority,
|
|
1984
|
+
target,
|
|
1985
|
+
writeIndex
|
|
1986
|
+
);
|
|
2102
1987
|
}
|
|
2103
1988
|
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
1989
|
+
/// <summary>
|
|
1990
|
+
/// WithoutContext sibling of <see cref="FillFlatHandlers{T}"/> for the
|
|
1991
|
+
/// targeted/broadcast slots whose delegates receive the routing
|
|
1992
|
+
/// InstanceId: fills fast (FastHandlerWithContext) entries followed by
|
|
1993
|
+
/// default (Action<InstanceId, T>, via the registration-time
|
|
1994
|
+
/// FastHandlerWithContext adapter) entries in registration order.
|
|
1995
|
+
/// Returns the next write index.
|
|
1996
|
+
/// </summary>
|
|
1997
|
+
internal int FillWithContextFlatHandlers<T>(
|
|
1998
|
+
IMessageBus messageBus,
|
|
1999
|
+
int priority,
|
|
2000
|
+
int fastIndex,
|
|
2001
|
+
int defaultIndex,
|
|
2002
|
+
ContextFlatDispatchEntry<T>[] target,
|
|
2003
|
+
int writeIndex
|
|
2107
2004
|
)
|
|
2108
2005
|
where T : IMessage
|
|
2109
2006
|
{
|
|
2110
|
-
TypedHandler<T> typedHandler
|
|
2111
|
-
|
|
2007
|
+
if (!GetHandlerForType(messageBus, out TypedHandler<T> typedHandler))
|
|
2008
|
+
{
|
|
2009
|
+
return writeIndex;
|
|
2010
|
+
}
|
|
2011
|
+
|
|
2012
|
+
writeIndex = FillFastWithContextFlatEntries(
|
|
2013
|
+
typedHandler.GetPriorityHandlers(fastIndex),
|
|
2014
|
+
priority,
|
|
2015
|
+
target,
|
|
2016
|
+
writeIndex
|
|
2017
|
+
);
|
|
2018
|
+
return FillDefaultWithContextFlatEntries(
|
|
2019
|
+
typedHandler.GetPriorityHandlers(defaultIndex),
|
|
2020
|
+
priority,
|
|
2021
|
+
target,
|
|
2022
|
+
writeIndex
|
|
2023
|
+
);
|
|
2112
2024
|
}
|
|
2113
2025
|
|
|
2114
2026
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
2115
|
-
|
|
2116
|
-
|
|
2027
|
+
private static Dictionary<int, IHandlerActionCache> GetContextPriorityHandlers<T>(
|
|
2028
|
+
TypedHandler<T> typedHandler,
|
|
2029
|
+
int slotIndex,
|
|
2030
|
+
InstanceId context
|
|
2117
2031
|
)
|
|
2118
2032
|
where T : IMessage
|
|
2119
2033
|
{
|
|
2120
|
-
|
|
2121
|
-
|
|
2034
|
+
Dictionary<InstanceId, Dictionary<int, IHandlerActionCache>> byContext =
|
|
2035
|
+
typedHandler.GetContextHandlers(slotIndex);
|
|
2036
|
+
if (
|
|
2037
|
+
byContext != null
|
|
2038
|
+
&& byContext.TryGetValue(
|
|
2039
|
+
context,
|
|
2040
|
+
out Dictionary<int, IHandlerActionCache> byPriority
|
|
2041
|
+
)
|
|
2042
|
+
)
|
|
2043
|
+
{
|
|
2044
|
+
return byPriority;
|
|
2045
|
+
}
|
|
2046
|
+
|
|
2047
|
+
return null;
|
|
2122
2048
|
}
|
|
2123
2049
|
|
|
2124
|
-
|
|
2050
|
+
private static int CountFlatDelegates<TDelegate>(
|
|
2051
|
+
Dictionary<int, IHandlerActionCache> byPriority,
|
|
2052
|
+
int priority
|
|
2053
|
+
)
|
|
2125
2054
|
{
|
|
2126
|
-
|
|
2055
|
+
if (
|
|
2056
|
+
byPriority != null
|
|
2057
|
+
&& byPriority.TryGetValue(priority, out IHandlerActionCache erased)
|
|
2058
|
+
&& erased is HandlerActionCache<TDelegate> cache
|
|
2059
|
+
)
|
|
2127
2060
|
{
|
|
2128
|
-
|
|
2129
|
-
/// Initializes an entry used to track handler invocation counts.
|
|
2130
|
-
/// </summary>
|
|
2131
|
-
/// <param name="handler">Handler delegate being tracked.</param>
|
|
2132
|
-
/// <param name="count">Number of times the handler has been cached.</param>
|
|
2133
|
-
public Entry(T handler, int count)
|
|
2134
|
-
{
|
|
2135
|
-
this.handler = handler;
|
|
2136
|
-
this.count = count;
|
|
2137
|
-
}
|
|
2138
|
-
|
|
2139
|
-
public readonly T handler;
|
|
2140
|
-
public readonly int count;
|
|
2061
|
+
return cache.insertionOrder.Count;
|
|
2141
2062
|
}
|
|
2142
2063
|
|
|
2143
|
-
|
|
2144
|
-
public readonly List<T> cache = new();
|
|
2145
|
-
public long version;
|
|
2146
|
-
public long lastSeenVersion = -1;
|
|
2147
|
-
public long lastSeenEmissionId;
|
|
2148
|
-
internal int prefreezeInvocationCount;
|
|
2064
|
+
return 0;
|
|
2149
2065
|
}
|
|
2150
2066
|
|
|
2151
|
-
|
|
2067
|
+
private int FillFastFlatEntries<T>(
|
|
2068
|
+
Dictionary<int, IHandlerActionCache> byPriority,
|
|
2069
|
+
int priority,
|
|
2070
|
+
FlatDispatchEntry<T>[] target,
|
|
2071
|
+
int writeIndex
|
|
2072
|
+
)
|
|
2152
2073
|
where T : IMessage
|
|
2153
2074
|
{
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2075
|
+
if (
|
|
2076
|
+
byPriority == null
|
|
2077
|
+
|| !byPriority.TryGetValue(priority, out IHandlerActionCache erased)
|
|
2078
|
+
|| erased is not HandlerActionCache<FastHandler<T>> cache
|
|
2079
|
+
)
|
|
2157
2080
|
{
|
|
2158
|
-
|
|
2081
|
+
return writeIndex;
|
|
2159
2082
|
}
|
|
2160
2083
|
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
ref T message,
|
|
2165
|
-
int priority,
|
|
2166
|
-
long emissionId
|
|
2167
|
-
)
|
|
2084
|
+
List<FastHandler<T>> ordered = cache.insertionOrder;
|
|
2085
|
+
int orderedCount = ordered.Count;
|
|
2086
|
+
for (int i = 0; i < orderedCount; ++i)
|
|
2168
2087
|
{
|
|
2169
|
-
if (
|
|
2088
|
+
if (
|
|
2089
|
+
cache.entries.TryGetValue(
|
|
2090
|
+
ordered[i],
|
|
2091
|
+
out HandlerActionCache<FastHandler<T>>.Entry entry
|
|
2092
|
+
)
|
|
2093
|
+
)
|
|
2170
2094
|
{
|
|
2171
|
-
|
|
2095
|
+
target[writeIndex++] = new FlatDispatchEntry<T>(this, entry.handler);
|
|
2172
2096
|
}
|
|
2173
|
-
|
|
2174
|
-
typedHandler.HandleUntargeted(ref message, priority, emissionId);
|
|
2175
2097
|
}
|
|
2098
|
+
|
|
2099
|
+
return writeIndex;
|
|
2176
2100
|
}
|
|
2177
2101
|
|
|
2178
|
-
|
|
2179
|
-
|
|
2102
|
+
private int FillDefaultFlatEntries<T>(
|
|
2103
|
+
Dictionary<int, IHandlerActionCache> byPriority,
|
|
2104
|
+
int priority,
|
|
2105
|
+
FlatDispatchEntry<T>[] target,
|
|
2106
|
+
int writeIndex
|
|
2107
|
+
)
|
|
2108
|
+
where T : IMessage
|
|
2180
2109
|
{
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2110
|
+
if (
|
|
2111
|
+
byPriority == null
|
|
2112
|
+
|| !byPriority.TryGetValue(priority, out IHandlerActionCache erased)
|
|
2113
|
+
|| erased is not HandlerActionCache<Action<T>> cache
|
|
2114
|
+
)
|
|
2184
2115
|
{
|
|
2185
|
-
|
|
2116
|
+
return writeIndex;
|
|
2186
2117
|
}
|
|
2187
2118
|
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
ref TMessage message,
|
|
2192
|
-
int priority,
|
|
2193
|
-
long emissionId
|
|
2194
|
-
)
|
|
2119
|
+
List<Action<T>> ordered = cache.insertionOrder;
|
|
2120
|
+
int orderedCount = ordered.Count;
|
|
2121
|
+
for (int i = 0; i < orderedCount; ++i)
|
|
2195
2122
|
{
|
|
2196
|
-
if (
|
|
2123
|
+
if (
|
|
2124
|
+
!cache.entries.TryGetValue(
|
|
2125
|
+
ordered[i],
|
|
2126
|
+
out HandlerActionCache<Action<T>>.Entry entry
|
|
2127
|
+
)
|
|
2128
|
+
)
|
|
2197
2129
|
{
|
|
2198
|
-
|
|
2130
|
+
continue;
|
|
2199
2131
|
}
|
|
2200
2132
|
|
|
2201
|
-
|
|
2133
|
+
// Every default registration path for the flattened slots
|
|
2134
|
+
// supplies the adapter at registration time (AddUntargetedHandler,
|
|
2135
|
+
// AddTargetedHandler, AddSourcedBroadcastHandler, and their
|
|
2136
|
+
// post-processor siblings). The type test doubles as a null
|
|
2137
|
+
// guard; a missing adapter would indicate a new registration
|
|
2138
|
+
// path that forgot to provide one.
|
|
2139
|
+
if (entry.flatInvoker is FastHandler<T> invoker)
|
|
2140
|
+
{
|
|
2141
|
+
target[writeIndex++] = new FlatDispatchEntry<T>(this, invoker);
|
|
2142
|
+
}
|
|
2143
|
+
else
|
|
2144
|
+
{
|
|
2145
|
+
System.Diagnostics.Debug.Assert(
|
|
2146
|
+
false,
|
|
2147
|
+
"Default registration is missing its FastHandler flat invoker; "
|
|
2148
|
+
+ "every Add*Handler/Add*PostProcessor default path must adapt "
|
|
2149
|
+
+ "the augmented handler at registration time."
|
|
2150
|
+
);
|
|
2151
|
+
}
|
|
2202
2152
|
}
|
|
2153
|
+
|
|
2154
|
+
return writeIndex;
|
|
2203
2155
|
}
|
|
2204
2156
|
|
|
2205
|
-
|
|
2206
|
-
|
|
2157
|
+
private int FillFastWithContextFlatEntries<T>(
|
|
2158
|
+
Dictionary<int, IHandlerActionCache> byPriority,
|
|
2159
|
+
int priority,
|
|
2160
|
+
ContextFlatDispatchEntry<T>[] target,
|
|
2161
|
+
int writeIndex
|
|
2162
|
+
)
|
|
2163
|
+
where T : IMessage
|
|
2207
2164
|
{
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2165
|
+
if (
|
|
2166
|
+
byPriority == null
|
|
2167
|
+
|| !byPriority.TryGetValue(priority, out IHandlerActionCache erased)
|
|
2168
|
+
|| erased is not HandlerActionCache<FastHandlerWithContext<T>> cache
|
|
2169
|
+
)
|
|
2211
2170
|
{
|
|
2212
|
-
|
|
2171
|
+
return writeIndex;
|
|
2213
2172
|
}
|
|
2214
2173
|
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
ref InstanceId target,
|
|
2219
|
-
ref TMessage message,
|
|
2220
|
-
int priority,
|
|
2221
|
-
long emissionId
|
|
2222
|
-
)
|
|
2174
|
+
List<FastHandlerWithContext<T>> ordered = cache.insertionOrder;
|
|
2175
|
+
int orderedCount = ordered.Count;
|
|
2176
|
+
for (int i = 0; i < orderedCount; ++i)
|
|
2223
2177
|
{
|
|
2224
|
-
|
|
2178
|
+
if (
|
|
2179
|
+
cache.entries.TryGetValue(
|
|
2180
|
+
ordered[i],
|
|
2181
|
+
out HandlerActionCache<FastHandlerWithContext<T>>.Entry entry
|
|
2182
|
+
)
|
|
2183
|
+
)
|
|
2184
|
+
{
|
|
2185
|
+
target[writeIndex++] = new ContextFlatDispatchEntry<T>(this, entry.handler);
|
|
2186
|
+
}
|
|
2225
2187
|
}
|
|
2188
|
+
|
|
2189
|
+
return writeIndex;
|
|
2226
2190
|
}
|
|
2227
2191
|
|
|
2228
|
-
|
|
2229
|
-
|
|
2192
|
+
private int FillDefaultWithContextFlatEntries<T>(
|
|
2193
|
+
Dictionary<int, IHandlerActionCache> byPriority,
|
|
2194
|
+
int priority,
|
|
2195
|
+
ContextFlatDispatchEntry<T>[] target,
|
|
2196
|
+
int writeIndex
|
|
2197
|
+
)
|
|
2198
|
+
where T : IMessage
|
|
2230
2199
|
{
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2200
|
+
if (
|
|
2201
|
+
byPriority == null
|
|
2202
|
+
|| !byPriority.TryGetValue(priority, out IHandlerActionCache erased)
|
|
2203
|
+
|| erased is not HandlerActionCache<Action<InstanceId, T>> cache
|
|
2204
|
+
)
|
|
2234
2205
|
{
|
|
2235
|
-
|
|
2206
|
+
return writeIndex;
|
|
2236
2207
|
}
|
|
2237
2208
|
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
ref InstanceId target,
|
|
2242
|
-
ref TMessage message,
|
|
2243
|
-
int priority,
|
|
2244
|
-
long emissionId
|
|
2245
|
-
)
|
|
2209
|
+
List<Action<InstanceId, T>> ordered = cache.insertionOrder;
|
|
2210
|
+
int orderedCount = ordered.Count;
|
|
2211
|
+
for (int i = 0; i < orderedCount; ++i)
|
|
2246
2212
|
{
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
)
|
|
2213
|
+
if (
|
|
2214
|
+
!cache.entries.TryGetValue(
|
|
2215
|
+
ordered[i],
|
|
2216
|
+
out HandlerActionCache<Action<InstanceId, T>>.Entry entry
|
|
2217
|
+
)
|
|
2218
|
+
)
|
|
2219
|
+
{
|
|
2220
|
+
continue;
|
|
2221
|
+
}
|
|
2222
|
+
|
|
2223
|
+
// See FillDefaultFlatEntries: the adapter is created once at
|
|
2224
|
+
// registration time (AddTargetedWithoutTargetingHandler,
|
|
2225
|
+
// AddSourcedBroadcastWithoutSourceHandler, and their
|
|
2226
|
+
// post-processor siblings).
|
|
2227
|
+
if (entry.flatInvoker is FastHandlerWithContext<T> invoker)
|
|
2228
|
+
{
|
|
2229
|
+
target[writeIndex++] = new ContextFlatDispatchEntry<T>(this, invoker);
|
|
2230
|
+
}
|
|
2231
|
+
else
|
|
2232
|
+
{
|
|
2233
|
+
System.Diagnostics.Debug.Assert(
|
|
2234
|
+
false,
|
|
2235
|
+
"Default with-context registration is missing its "
|
|
2236
|
+
+ "FastHandlerWithContext flat invoker; every without-context "
|
|
2237
|
+
+ "Add* default path must adapt the augmented handler at "
|
|
2238
|
+
+ "registration time."
|
|
2239
|
+
);
|
|
2240
|
+
}
|
|
2253
2241
|
}
|
|
2242
|
+
|
|
2243
|
+
return writeIndex;
|
|
2254
2244
|
}
|
|
2255
2245
|
|
|
2256
|
-
internal sealed class
|
|
2257
|
-
where TMessage : IMessage
|
|
2246
|
+
internal sealed class HandlerActionCache<T> : DxMessaging.Core.Internal.IHandlerActionCache
|
|
2258
2247
|
{
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2248
|
+
// Uses outer T as a field type -- reflection callers must close
|
|
2249
|
+
// via MakeGenericType(outer.GetGenericArguments()) before passing
|
|
2250
|
+
// this type to Activator.CreateInstance. See
|
|
2251
|
+
// Tests/Editor/Contract/ReflectionHelpers.cs::CloseNestedGeneric.
|
|
2252
|
+
internal readonly struct Entry
|
|
2262
2253
|
{
|
|
2263
|
-
|
|
2264
|
-
|
|
2254
|
+
/// <summary>
|
|
2255
|
+
/// Initializes an entry used to track handler invocation counts.
|
|
2256
|
+
/// </summary>
|
|
2257
|
+
/// <param name="handler">Handler delegate being tracked.</param>
|
|
2258
|
+
/// <param name="count">Number of times the handler has been cached.</param>
|
|
2259
|
+
public Entry(T handler, int count)
|
|
2260
|
+
: this(handler, count, null) { }
|
|
2265
2261
|
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2262
|
+
/// <summary>
|
|
2263
|
+
/// Initializes an entry that additionally carries a pre-resolved
|
|
2264
|
+
/// flat-dispatch invoker (see <see cref="flatInvoker"/>).
|
|
2265
|
+
/// </summary>
|
|
2266
|
+
/// <param name="handler">Handler delegate being tracked.</param>
|
|
2267
|
+
/// <param name="count">Number of times the handler has been cached.</param>
|
|
2268
|
+
/// <param name="flatInvoker">Pre-resolved flat-dispatch invoker, if any.</param>
|
|
2269
|
+
public Entry(T handler, int count, object flatInvoker)
|
|
2270
|
+
{
|
|
2271
|
+
this.handler = handler;
|
|
2272
|
+
this.count = count;
|
|
2273
|
+
this.flatInvoker = flatInvoker;
|
|
2274
|
+
}
|
|
2275
|
+
|
|
2276
|
+
public readonly T handler;
|
|
2277
|
+
public readonly int count;
|
|
2278
|
+
|
|
2279
|
+
// Pre-resolved invoker consumed by the bus-side flat dispatch
|
|
2280
|
+
// snapshot (MessageBus.BuildMessageFlatDispatch). For
|
|
2281
|
+
// default Action<TMessage> registrations this holds a
|
|
2282
|
+
// FastHandler<TMessage> adapter wrapping the AUGMENTED
|
|
2283
|
+
// handler, created exactly ONCE at registration time so
|
|
2284
|
+
// snapshot rebuilds never allocate closures. For delegate
|
|
2285
|
+
// shapes the flat path does not consume (fast handlers, which
|
|
2286
|
+
// already ARE the invoker, and every targeted/broadcast
|
|
2287
|
+
// shape) this stays null. Refcount increments and decrements
|
|
2288
|
+
// preserve the first registration's invoker, mirroring the
|
|
2289
|
+
// first-augmented-handler-wins semantics of `handler`.
|
|
2290
|
+
public readonly object flatInvoker;
|
|
2281
2291
|
}
|
|
2282
|
-
}
|
|
2283
2292
|
|
|
2284
|
-
|
|
2285
|
-
where TMessage : IMessage
|
|
2286
|
-
{
|
|
2287
|
-
private readonly TypedHandler<TMessage> typedHandler;
|
|
2293
|
+
public readonly Dictionary<T, Entry> entries = new();
|
|
2288
2294
|
|
|
2289
|
-
|
|
2295
|
+
// Original-handler keys in first-registration order. Dictionary
|
|
2296
|
+
// enumeration order is NOT stable across Remove/Add churn (.NET
|
|
2297
|
+
// reuses freed slots LIFO), so dispatch snapshots are rebuilt from
|
|
2298
|
+
// this list instead of from <see cref="entries"/> to honor the
|
|
2299
|
+
// documented "same priority uses registration order" contract.
|
|
2300
|
+
// Invariants: contains exactly the keys of <see cref="entries"/>;
|
|
2301
|
+
// a key is appended on its FIRST registration only (refcount
|
|
2302
|
+
// increments do not move it) and removed when its refcount drops
|
|
2303
|
+
// to zero. Maintained exclusively by the AddHandler* family and
|
|
2304
|
+
// <see cref="DxMessaging.Core.Internal.IHandlerActionCache.Reset"/>.
|
|
2305
|
+
public readonly List<T> insertionOrder = new();
|
|
2306
|
+
public readonly List<T> cache = new();
|
|
2307
|
+
public long version;
|
|
2308
|
+
public long lastSeenVersion = -1;
|
|
2309
|
+
public long lastSeenEmissionId = -1;
|
|
2310
|
+
|
|
2311
|
+
/// <summary>Monotonic version field, read-only on the interface surface.</summary>
|
|
2312
|
+
long DxMessaging.Core.Internal.IHandlerActionCache.Version
|
|
2290
2313
|
{
|
|
2291
|
-
|
|
2314
|
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
2315
|
+
get => version;
|
|
2292
2316
|
}
|
|
2293
2317
|
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
MessageHandler messageHandler,
|
|
2297
|
-
ref InstanceId target,
|
|
2298
|
-
ref TMessage message,
|
|
2299
|
-
int priority,
|
|
2300
|
-
long emissionId
|
|
2301
|
-
)
|
|
2318
|
+
/// <summary>Most recent dispatcher-observed version; mutable through the staged dispatch path.</summary>
|
|
2319
|
+
long DxMessaging.Core.Internal.IHandlerActionCache.LastSeenVersion
|
|
2302
2320
|
{
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
emissionId
|
|
2308
|
-
);
|
|
2321
|
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
2322
|
+
get => lastSeenVersion;
|
|
2323
|
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
2324
|
+
set => lastSeenVersion = value;
|
|
2309
2325
|
}
|
|
2310
|
-
}
|
|
2311
|
-
|
|
2312
|
-
internal sealed class BroadcastDispatchLink<TMessage>
|
|
2313
|
-
where TMessage : IMessage
|
|
2314
|
-
{
|
|
2315
|
-
private readonly TypedHandler<TMessage> typedHandler;
|
|
2316
2326
|
|
|
2317
|
-
|
|
2327
|
+
/// <summary>Most recent dispatcher-observed bus emission id.</summary>
|
|
2328
|
+
long DxMessaging.Core.Internal.IHandlerActionCache.LastSeenEmissionId
|
|
2318
2329
|
{
|
|
2319
|
-
|
|
2330
|
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
2331
|
+
get => lastSeenEmissionId;
|
|
2332
|
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
2333
|
+
set => lastSeenEmissionId = value;
|
|
2320
2334
|
}
|
|
2321
2335
|
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
MessageHandler messageHandler,
|
|
2325
|
-
ref InstanceId source,
|
|
2326
|
-
ref TMessage message,
|
|
2327
|
-
int priority,
|
|
2328
|
-
long emissionId
|
|
2329
|
-
)
|
|
2336
|
+
/// <summary>True iff the entries dictionary holds zero handlers.</summary>
|
|
2337
|
+
bool DxMessaging.Core.Internal.IHandlerActionCache.IsEmpty
|
|
2330
2338
|
{
|
|
2331
|
-
|
|
2339
|
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
2340
|
+
get => entries.Count == 0;
|
|
2341
|
+
}
|
|
2342
|
+
|
|
2343
|
+
/// <summary>
|
|
2344
|
+
/// Eviction-driven full clear; bumps <see cref="version"/> as the LAST step
|
|
2345
|
+
/// so captured dispatch closures observe invalidation.
|
|
2346
|
+
/// </summary>
|
|
2347
|
+
void DxMessaging.Core.Internal.IHandlerActionCache.Reset()
|
|
2348
|
+
{
|
|
2349
|
+
entries.Clear();
|
|
2350
|
+
insertionOrder.Clear();
|
|
2351
|
+
cache.Clear();
|
|
2352
|
+
lastSeenVersion = -1;
|
|
2353
|
+
lastSeenEmissionId = -1;
|
|
2354
|
+
unchecked
|
|
2355
|
+
{
|
|
2356
|
+
++version;
|
|
2357
|
+
}
|
|
2332
2358
|
}
|
|
2333
2359
|
}
|
|
2334
2360
|
|
|
2335
|
-
|
|
2336
|
-
|
|
2361
|
+
/// <summary>
|
|
2362
|
+
/// One-size-fits-all wrapper around all possible Messaging sinks for a particular MessageHandler & MessageType.
|
|
2363
|
+
/// </summary>
|
|
2364
|
+
/// <typeparam name="T">Message type that this Handler exists to serve.</typeparam>
|
|
2365
|
+
internal sealed class TypedHandler<T> : ITypedHandlerSlotSweeper
|
|
2366
|
+
where T : IMessage
|
|
2337
2367
|
{
|
|
2338
|
-
|
|
2368
|
+
// Typed storage: 20 typed slots + 6 global slots. The legacy
|
|
2369
|
+
// named fields were deleted so new handler variants must pick an
|
|
2370
|
+
// explicit axis-indexed slot.
|
|
2371
|
+
internal readonly TypedSlot<T>[] _slots = new TypedSlot<T>[TypedSlotIndex.Length];
|
|
2372
|
+
internal readonly TypedGlobalSlot[] _globalSlots = new TypedGlobalSlot[
|
|
2373
|
+
TypedGlobalSlotIndex.Length
|
|
2374
|
+
];
|
|
2339
2375
|
|
|
2340
|
-
|
|
2376
|
+
// Constructor exists solely so the [Conditional("DEBUG")]
|
|
2377
|
+
// validator below runs at construction time. In Release builds
|
|
2378
|
+
// the Conditional attribute strips the call site, leaving an
|
|
2379
|
+
// empty constructor body that the JIT collapses to the
|
|
2380
|
+
// equivalent of the implicit default. Mirrors the
|
|
2381
|
+
// MessageBus.ValidateSinkArrays() pattern.
|
|
2382
|
+
internal TypedHandler()
|
|
2341
2383
|
{
|
|
2342
|
-
|
|
2384
|
+
ValidateSlotArrays();
|
|
2343
2385
|
}
|
|
2344
2386
|
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
ref InstanceId source,
|
|
2349
|
-
ref TMessage message,
|
|
2350
|
-
int priority,
|
|
2351
|
-
long emissionId
|
|
2352
|
-
)
|
|
2387
|
+
internal bool _markedForOuterRemoval;
|
|
2388
|
+
|
|
2389
|
+
int ITypedHandlerSlotSweeper.MessageTypeIndex
|
|
2353
2390
|
{
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
ref message,
|
|
2357
|
-
priority,
|
|
2358
|
-
emissionId
|
|
2359
|
-
);
|
|
2391
|
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
2392
|
+
get => MessageHelperIndexer<T>.SequentialId;
|
|
2360
2393
|
}
|
|
2361
|
-
}
|
|
2362
2394
|
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2395
|
+
bool ITypedHandlerSlotSweeper.MarkedForOuterRemoval
|
|
2396
|
+
{
|
|
2397
|
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
2398
|
+
get => _markedForOuterRemoval;
|
|
2399
|
+
}
|
|
2367
2400
|
|
|
2368
|
-
|
|
2401
|
+
[Conditional("DEBUG")]
|
|
2402
|
+
private void ValidateSlotArrays()
|
|
2369
2403
|
{
|
|
2370
|
-
|
|
2404
|
+
if (_slots.Length != TypedSlotIndex.Length)
|
|
2405
|
+
{
|
|
2406
|
+
throw new InvalidOperationException(
|
|
2407
|
+
$"_slots length is {_slots.Length} but TypedSlotIndex.Length is {TypedSlotIndex.Length}."
|
|
2408
|
+
);
|
|
2409
|
+
}
|
|
2410
|
+
if (_globalSlots.Length != TypedGlobalSlotIndex.Length)
|
|
2411
|
+
{
|
|
2412
|
+
throw new InvalidOperationException(
|
|
2413
|
+
$"_globalSlots length is {_globalSlots.Length} but TypedGlobalSlotIndex.Length is {TypedGlobalSlotIndex.Length}."
|
|
2414
|
+
);
|
|
2415
|
+
}
|
|
2416
|
+
// Lazy registration writers update the slot arrays; this assertion still
|
|
2417
|
+
// holds at construction (slots populate on first register,
|
|
2418
|
+
// not on construction). The invariant flips meaning -- not
|
|
2419
|
+
// the message -- when writers land.
|
|
2420
|
+
for (int i = 0; i < _slots.Length; ++i)
|
|
2421
|
+
{
|
|
2422
|
+
if (_slots[i] != null)
|
|
2423
|
+
{
|
|
2424
|
+
throw new InvalidOperationException(
|
|
2425
|
+
$"_slots[{i}] is non-null at construction; expected null per TypedSlotIndex because slots populate lazily on first registration."
|
|
2426
|
+
);
|
|
2427
|
+
}
|
|
2428
|
+
}
|
|
2429
|
+
for (int i = 0; i < _globalSlots.Length; ++i)
|
|
2430
|
+
{
|
|
2431
|
+
if (_globalSlots[i] != null)
|
|
2432
|
+
{
|
|
2433
|
+
throw new InvalidOperationException(
|
|
2434
|
+
$"_globalSlots[{i}] is non-null at construction; expected null per TypedGlobalSlotIndex because slots populate lazily on first registration."
|
|
2435
|
+
);
|
|
2436
|
+
}
|
|
2437
|
+
}
|
|
2371
2438
|
}
|
|
2372
2439
|
|
|
2373
2440
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
2374
|
-
|
|
2375
|
-
MessageHandler messageHandler,
|
|
2376
|
-
ref InstanceId source,
|
|
2377
|
-
ref TMessage message,
|
|
2378
|
-
int priority,
|
|
2379
|
-
long emissionId
|
|
2380
|
-
)
|
|
2441
|
+
private TypedSlot<T> GetOrCreateSlot(int index, bool requiresContext)
|
|
2381
2442
|
{
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
}
|
|
2389
|
-
}
|
|
2443
|
+
TypedSlot<T> slot = _slots[index];
|
|
2444
|
+
if (slot == null)
|
|
2445
|
+
{
|
|
2446
|
+
slot = new TypedSlot<T>(requiresContext);
|
|
2447
|
+
_slots[index] = slot;
|
|
2448
|
+
}
|
|
2390
2449
|
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
{
|
|
2394
|
-
private readonly TypedHandler<TMessage> typedHandler;
|
|
2450
|
+
return slot;
|
|
2451
|
+
}
|
|
2395
2452
|
|
|
2396
|
-
|
|
2453
|
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
2454
|
+
internal Dictionary<int, IHandlerActionCache> GetOrCreatePriorityHandlers(
|
|
2455
|
+
int index,
|
|
2456
|
+
bool requiresContext
|
|
2457
|
+
)
|
|
2397
2458
|
{
|
|
2398
|
-
|
|
2459
|
+
return GetOrCreateSlot(index, requiresContext).byPriority;
|
|
2399
2460
|
}
|
|
2400
2461
|
|
|
2401
2462
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
2402
|
-
internal
|
|
2403
|
-
MessageHandler messageHandler,
|
|
2404
|
-
ref InstanceId source,
|
|
2405
|
-
ref TMessage message,
|
|
2406
|
-
int priority,
|
|
2407
|
-
long emissionId
|
|
2408
|
-
)
|
|
2463
|
+
internal Dictionary<int, IHandlerActionCache> GetPriorityHandlers(int index)
|
|
2409
2464
|
{
|
|
2410
|
-
|
|
2411
|
-
ref source,
|
|
2412
|
-
ref message,
|
|
2413
|
-
priority,
|
|
2414
|
-
emissionId
|
|
2415
|
-
);
|
|
2465
|
+
return _slots[index]?.byPriority;
|
|
2416
2466
|
}
|
|
2417
|
-
}
|
|
2418
2467
|
|
|
2419
|
-
|
|
2420
|
-
/// One-size-fits-all wrapper around all possible Messaging sinks for a particular MessageHandler & MessageType.
|
|
2421
|
-
/// </summary>
|
|
2422
|
-
/// <typeparam name="T">Message type that this Handler exists to serve.</typeparam>
|
|
2423
|
-
internal sealed class TypedHandler<T>
|
|
2424
|
-
where T : IMessage
|
|
2425
|
-
{
|
|
2426
|
-
internal Dictionary<
|
|
2427
|
-
InstanceId,
|
|
2428
|
-
Dictionary<int, HandlerActionCache<Action<T>>>
|
|
2429
|
-
> _targetedHandlers;
|
|
2430
|
-
internal Dictionary<int, HandlerActionCache<Action<T>>> _untargetedHandlers;
|
|
2431
|
-
internal Dictionary<
|
|
2432
|
-
InstanceId,
|
|
2433
|
-
Dictionary<int, HandlerActionCache<Action<T>>>
|
|
2434
|
-
> _broadcastHandlers;
|
|
2435
|
-
internal Dictionary<
|
|
2436
|
-
InstanceId,
|
|
2437
|
-
Dictionary<int, HandlerActionCache<Action<T>>>
|
|
2438
|
-
> _targetedPostProcessingHandlers;
|
|
2439
|
-
internal Dictionary<
|
|
2440
|
-
int,
|
|
2441
|
-
HandlerActionCache<Action<T>>
|
|
2442
|
-
> _untargetedPostProcessingHandlers;
|
|
2443
|
-
internal Dictionary<
|
|
2444
|
-
InstanceId,
|
|
2445
|
-
Dictionary<int, HandlerActionCache<Action<T>>>
|
|
2446
|
-
> _broadcastPostProcessingHandlers;
|
|
2447
|
-
internal Dictionary<
|
|
2448
|
-
InstanceId,
|
|
2449
|
-
Dictionary<int, HandlerActionCache<FastHandler<T>>>
|
|
2450
|
-
> _targetedFastHandlers;
|
|
2451
|
-
internal Dictionary<int, HandlerActionCache<FastHandler<T>>> _untargetedFastHandlers;
|
|
2452
|
-
internal Dictionary<
|
|
2453
|
-
InstanceId,
|
|
2454
|
-
Dictionary<int, HandlerActionCache<FastHandler<T>>>
|
|
2455
|
-
> _broadcastFastHandlers;
|
|
2456
|
-
internal Dictionary<
|
|
2457
|
-
InstanceId,
|
|
2458
|
-
Dictionary<int, HandlerActionCache<FastHandler<T>>>
|
|
2459
|
-
> _targetedPostProcessingFastHandlers;
|
|
2460
|
-
internal Dictionary<
|
|
2461
|
-
int,
|
|
2462
|
-
HandlerActionCache<FastHandler<T>>
|
|
2463
|
-
> _untargetedPostProcessingFastHandlers;
|
|
2468
|
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
2464
2469
|
internal Dictionary<
|
|
2465
2470
|
InstanceId,
|
|
2466
|
-
Dictionary<int,
|
|
2467
|
-
>
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
> _globalTargetedHandlers;
|
|
2474
|
-
|
|
2475
|
-
internal HandlerActionCache<
|
|
2476
|
-
Action<InstanceId, IBroadcastMessage>
|
|
2477
|
-
> _globalBroadcastHandlers;
|
|
2478
|
-
|
|
2479
|
-
internal HandlerActionCache<
|
|
2480
|
-
FastHandler<IUntargetedMessage>
|
|
2481
|
-
> _globalUntargetedFastHandlers;
|
|
2482
|
-
|
|
2483
|
-
internal HandlerActionCache<
|
|
2484
|
-
FastHandlerWithContext<ITargetedMessage>
|
|
2485
|
-
> _globalTargetedFastHandlers;
|
|
2471
|
+
Dictionary<int, IHandlerActionCache>
|
|
2472
|
+
> GetOrCreateContextHandlers(int index)
|
|
2473
|
+
{
|
|
2474
|
+
TypedSlot<T> slot = GetOrCreateSlot(index, requiresContext: true);
|
|
2475
|
+
slot.byContext ??= DxPools.TypedHandlerContextDicts.Rent();
|
|
2476
|
+
return slot.byContext;
|
|
2477
|
+
}
|
|
2486
2478
|
|
|
2487
|
-
|
|
2488
|
-
FastHandlerWithContext<IBroadcastMessage>
|
|
2489
|
-
> _globalBroadcastFastHandlers;
|
|
2490
|
-
internal Dictionary<
|
|
2491
|
-
int,
|
|
2492
|
-
HandlerActionCache<Action<InstanceId, T>>
|
|
2493
|
-
> _targetedWithoutTargetingHandlers;
|
|
2494
|
-
internal Dictionary<
|
|
2495
|
-
int,
|
|
2496
|
-
HandlerActionCache<FastHandlerWithContext<T>>
|
|
2497
|
-
> _fastTargetedWithoutTargetingHandlers;
|
|
2498
|
-
internal Dictionary<
|
|
2499
|
-
int,
|
|
2500
|
-
HandlerActionCache<Action<InstanceId, T>>
|
|
2501
|
-
> _broadcastWithoutSourceHandlers;
|
|
2502
|
-
internal Dictionary<
|
|
2503
|
-
int,
|
|
2504
|
-
HandlerActionCache<FastHandlerWithContext<T>>
|
|
2505
|
-
> _fastBroadcastWithoutSourceHandlers;
|
|
2506
|
-
internal Dictionary<
|
|
2507
|
-
int,
|
|
2508
|
-
HandlerActionCache<Action<InstanceId, T>>
|
|
2509
|
-
> _targetedWithoutTargetingPostProcessingHandlers;
|
|
2510
|
-
internal Dictionary<
|
|
2511
|
-
int,
|
|
2512
|
-
HandlerActionCache<FastHandlerWithContext<T>>
|
|
2513
|
-
> _fastTargetedWithoutTargetingPostProcessingHandlers;
|
|
2514
|
-
internal Dictionary<
|
|
2515
|
-
int,
|
|
2516
|
-
HandlerActionCache<Action<InstanceId, T>>
|
|
2517
|
-
> _broadcastWithoutSourcePostProcessingHandlers;
|
|
2479
|
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
2518
2480
|
internal Dictionary<
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
>
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
private object _targetedPostLink;
|
|
2526
|
-
private object _targetedWithoutTargetingLink;
|
|
2527
|
-
private object _targetedWithoutTargetingPostLink;
|
|
2528
|
-
private object _broadcastLink;
|
|
2529
|
-
private object _broadcastPostLink;
|
|
2530
|
-
private object _broadcastWithoutSourceLink;
|
|
2531
|
-
private object _broadcastWithoutSourcePostLink;
|
|
2481
|
+
InstanceId,
|
|
2482
|
+
Dictionary<int, IHandlerActionCache>
|
|
2483
|
+
> GetContextHandlers(int index)
|
|
2484
|
+
{
|
|
2485
|
+
return _slots[index]?.byContext;
|
|
2486
|
+
}
|
|
2532
2487
|
|
|
2533
2488
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
2534
|
-
internal
|
|
2489
|
+
internal TypedGlobalSlot GetOrCreateGlobalSlot(int index)
|
|
2535
2490
|
{
|
|
2536
|
-
|
|
2537
|
-
if (
|
|
2491
|
+
TypedGlobalSlot slot = _globalSlots[index];
|
|
2492
|
+
if (slot == null)
|
|
2538
2493
|
{
|
|
2539
|
-
|
|
2540
|
-
|
|
2494
|
+
slot = new TypedGlobalSlot();
|
|
2495
|
+
_globalSlots[index] = slot;
|
|
2541
2496
|
}
|
|
2542
2497
|
|
|
2543
|
-
return
|
|
2498
|
+
return slot;
|
|
2544
2499
|
}
|
|
2545
2500
|
|
|
2546
2501
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
2547
|
-
internal
|
|
2502
|
+
internal HandlerActionCache<TU> GetGlobalCache<TU>(int index)
|
|
2548
2503
|
{
|
|
2549
|
-
|
|
2550
|
-
_untargetedPostLink as UntargetedPostDispatchLink<T>;
|
|
2551
|
-
if (link == null)
|
|
2552
|
-
{
|
|
2553
|
-
link = new UntargetedPostDispatchLink<T>(this);
|
|
2554
|
-
_untargetedPostLink = link;
|
|
2555
|
-
}
|
|
2556
|
-
|
|
2557
|
-
return link;
|
|
2504
|
+
return _globalSlots[index]?.cache as HandlerActionCache<TU>;
|
|
2558
2505
|
}
|
|
2559
2506
|
|
|
2560
2507
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
2561
|
-
|
|
2508
|
+
private TypedSlot<T> FindPrioritySlot(Dictionary<int, IHandlerActionCache> handlers)
|
|
2562
2509
|
{
|
|
2563
|
-
|
|
2564
|
-
if (link == null)
|
|
2510
|
+
for (int i = 0; i < _slots.Length; ++i)
|
|
2565
2511
|
{
|
|
2566
|
-
|
|
2567
|
-
|
|
2512
|
+
TypedSlot<T> slot = _slots[i];
|
|
2513
|
+
if (slot != null && ReferenceEquals(slot.byPriority, handlers))
|
|
2514
|
+
{
|
|
2515
|
+
return slot;
|
|
2516
|
+
}
|
|
2568
2517
|
}
|
|
2569
2518
|
|
|
2570
|
-
return
|
|
2519
|
+
return null;
|
|
2571
2520
|
}
|
|
2572
2521
|
|
|
2573
2522
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
2574
|
-
|
|
2523
|
+
private TypedSlot<T> FindContextSlot(
|
|
2524
|
+
Dictionary<InstanceId, Dictionary<int, IHandlerActionCache>> handlersByContext
|
|
2525
|
+
)
|
|
2575
2526
|
{
|
|
2576
|
-
|
|
2577
|
-
if (link == null)
|
|
2527
|
+
for (int i = 0; i < _slots.Length; ++i)
|
|
2578
2528
|
{
|
|
2579
|
-
|
|
2580
|
-
|
|
2529
|
+
TypedSlot<T> slot = _slots[i];
|
|
2530
|
+
if (slot != null && ReferenceEquals(slot.byContext, handlersByContext))
|
|
2531
|
+
{
|
|
2532
|
+
return slot;
|
|
2533
|
+
}
|
|
2581
2534
|
}
|
|
2582
2535
|
|
|
2583
|
-
return
|
|
2536
|
+
return null;
|
|
2584
2537
|
}
|
|
2585
2538
|
|
|
2586
|
-
|
|
2587
|
-
internal TargetedWithoutTargetingDispatchLink<T> GetOrCreateTargetedWithoutTargetingLink()
|
|
2539
|
+
int ITypedHandlerSlotSweeper.ResetEmptySlotsForSweep()
|
|
2588
2540
|
{
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2541
|
+
_markedForOuterRemoval = false;
|
|
2542
|
+
int resetCount = 0;
|
|
2543
|
+
for (int i = 0; i < _slots.Length; ++i)
|
|
2544
|
+
{
|
|
2545
|
+
TypedSlot<T> slot = _slots[i];
|
|
2546
|
+
if (slot != null && slot.IsEmpty)
|
|
2547
|
+
{
|
|
2548
|
+
slot.Reset();
|
|
2549
|
+
_slots[i] = null;
|
|
2550
|
+
resetCount++;
|
|
2551
|
+
}
|
|
2552
|
+
}
|
|
2553
|
+
|
|
2554
|
+
for (int i = 0; i < _globalSlots.Length; ++i)
|
|
2592
2555
|
{
|
|
2593
|
-
|
|
2594
|
-
|
|
2556
|
+
TypedGlobalSlot slot = _globalSlots[i];
|
|
2557
|
+
if (slot != null && slot.IsEmpty)
|
|
2558
|
+
{
|
|
2559
|
+
slot.Reset();
|
|
2560
|
+
_globalSlots[i] = null;
|
|
2561
|
+
resetCount++;
|
|
2562
|
+
}
|
|
2595
2563
|
}
|
|
2596
2564
|
|
|
2597
|
-
|
|
2565
|
+
MarkForOuterRemovalIfEmpty();
|
|
2566
|
+
return resetCount;
|
|
2598
2567
|
}
|
|
2599
2568
|
|
|
2600
|
-
|
|
2601
|
-
internal TargetedWithoutTargetingPostDispatchLink<T> GetOrCreateTargetedWithoutTargetingPostLink()
|
|
2569
|
+
int ITypedHandlerSlotSweeper.ResetAllSlotsForBusReset()
|
|
2602
2570
|
{
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
if (link == null)
|
|
2571
|
+
_markedForOuterRemoval = false;
|
|
2572
|
+
int resetCount = 0;
|
|
2573
|
+
for (int i = 0; i < _slots.Length; ++i)
|
|
2607
2574
|
{
|
|
2608
|
-
|
|
2609
|
-
|
|
2575
|
+
TypedSlot<T> slot = _slots[i];
|
|
2576
|
+
if (slot != null)
|
|
2577
|
+
{
|
|
2578
|
+
slot.Reset();
|
|
2579
|
+
_slots[i] = null;
|
|
2580
|
+
resetCount++;
|
|
2581
|
+
}
|
|
2610
2582
|
}
|
|
2611
2583
|
|
|
2612
|
-
|
|
2584
|
+
for (int i = 0; i < _globalSlots.Length; ++i)
|
|
2585
|
+
{
|
|
2586
|
+
TypedGlobalSlot slot = _globalSlots[i];
|
|
2587
|
+
if (slot != null)
|
|
2588
|
+
{
|
|
2589
|
+
slot.Reset();
|
|
2590
|
+
_globalSlots[i] = null;
|
|
2591
|
+
resetCount++;
|
|
2592
|
+
}
|
|
2593
|
+
}
|
|
2594
|
+
|
|
2595
|
+
return resetCount;
|
|
2613
2596
|
}
|
|
2614
2597
|
|
|
2615
|
-
|
|
2616
|
-
internal BroadcastDispatchLink<T> GetOrCreateBroadcastLink()
|
|
2598
|
+
int ITypedHandlerSlotSweeper.CountEmptySlotsForSweep()
|
|
2617
2599
|
{
|
|
2618
|
-
|
|
2619
|
-
|
|
2600
|
+
int count = 0;
|
|
2601
|
+
for (int i = 0; i < _slots.Length; ++i)
|
|
2620
2602
|
{
|
|
2621
|
-
|
|
2622
|
-
|
|
2603
|
+
TypedSlot<T> slot = _slots[i];
|
|
2604
|
+
if (slot != null && slot.IsEmpty)
|
|
2605
|
+
{
|
|
2606
|
+
count++;
|
|
2607
|
+
}
|
|
2608
|
+
}
|
|
2609
|
+
|
|
2610
|
+
for (int i = 0; i < _globalSlots.Length; ++i)
|
|
2611
|
+
{
|
|
2612
|
+
TypedGlobalSlot slot = _globalSlots[i];
|
|
2613
|
+
if (slot != null && slot.IsEmpty)
|
|
2614
|
+
{
|
|
2615
|
+
count++;
|
|
2616
|
+
}
|
|
2623
2617
|
}
|
|
2624
2618
|
|
|
2625
|
-
return
|
|
2619
|
+
return count;
|
|
2626
2620
|
}
|
|
2627
2621
|
|
|
2628
2622
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
2629
|
-
|
|
2623
|
+
private void MarkForOuterRemovalIfEmpty()
|
|
2630
2624
|
{
|
|
2631
|
-
|
|
2632
|
-
_broadcastPostLink as BroadcastPostDispatchLink<T>;
|
|
2633
|
-
if (link == null)
|
|
2625
|
+
if (HasLiveSlots())
|
|
2634
2626
|
{
|
|
2635
|
-
|
|
2636
|
-
_broadcastPostLink = link;
|
|
2627
|
+
return;
|
|
2637
2628
|
}
|
|
2638
2629
|
|
|
2639
|
-
|
|
2630
|
+
_markedForOuterRemoval = true;
|
|
2640
2631
|
}
|
|
2641
2632
|
|
|
2642
2633
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
2643
|
-
|
|
2634
|
+
private bool HasLiveSlots()
|
|
2644
2635
|
{
|
|
2645
|
-
|
|
2646
|
-
_broadcastWithoutSourceLink as BroadcastWithoutSourceDispatchLink<T>;
|
|
2647
|
-
if (link == null)
|
|
2636
|
+
for (int i = 0; i < _slots.Length; ++i)
|
|
2648
2637
|
{
|
|
2649
|
-
|
|
2650
|
-
|
|
2638
|
+
if (_slots[i] != null)
|
|
2639
|
+
{
|
|
2640
|
+
return true;
|
|
2641
|
+
}
|
|
2651
2642
|
}
|
|
2652
2643
|
|
|
2653
|
-
|
|
2654
|
-
}
|
|
2655
|
-
|
|
2656
|
-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
2657
|
-
internal BroadcastWithoutSourcePostDispatchLink<T> GetOrCreateBroadcastWithoutSourcePostLink()
|
|
2658
|
-
{
|
|
2659
|
-
BroadcastWithoutSourcePostDispatchLink<T> link =
|
|
2660
|
-
_broadcastWithoutSourcePostLink as BroadcastWithoutSourcePostDispatchLink<T>;
|
|
2661
|
-
if (link == null)
|
|
2644
|
+
for (int i = 0; i < _globalSlots.Length; ++i)
|
|
2662
2645
|
{
|
|
2663
|
-
|
|
2664
|
-
|
|
2646
|
+
if (_globalSlots[i] != null)
|
|
2647
|
+
{
|
|
2648
|
+
return true;
|
|
2649
|
+
}
|
|
2665
2650
|
}
|
|
2666
2651
|
|
|
2667
|
-
return
|
|
2652
|
+
return false;
|
|
2668
2653
|
}
|
|
2669
2654
|
|
|
2670
2655
|
/// <summary>
|
|
@@ -2674,19 +2659,18 @@ namespace DxMessaging.Core
|
|
|
2674
2659
|
/// <param name="priority">Priority at which to run the handlers.</param>
|
|
2675
2660
|
public void HandleUntargeted(ref T message, int priority, long emissionId)
|
|
2676
2661
|
{
|
|
2677
|
-
|
|
2678
|
-
|
|
2662
|
+
RunFastHandlers(
|
|
2663
|
+
GetPriorityHandlers(TypedSlotIndex.UntargetedHandleFast),
|
|
2664
|
+
ref message,
|
|
2679
2665
|
priority,
|
|
2680
2666
|
emissionId
|
|
2681
2667
|
);
|
|
2682
|
-
|
|
2683
|
-
|
|
2668
|
+
RunHandlers(
|
|
2669
|
+
GetPriorityHandlers(TypedSlotIndex.UntargetedHandleDefault),
|
|
2670
|
+
ref message,
|
|
2684
2671
|
priority,
|
|
2685
2672
|
emissionId
|
|
2686
2673
|
);
|
|
2687
|
-
|
|
2688
|
-
RunFastHandlers(_untargetedFastHandlers, ref message, priority, emissionId);
|
|
2689
|
-
RunHandlers(_untargetedHandlers, ref message, priority, emissionId);
|
|
2690
2674
|
}
|
|
2691
2675
|
|
|
2692
2676
|
/// <summary>
|
|
@@ -2704,14 +2688,14 @@ namespace DxMessaging.Core
|
|
|
2704
2688
|
{
|
|
2705
2689
|
RunFastHandlersWithContext(
|
|
2706
2690
|
ref target,
|
|
2707
|
-
|
|
2691
|
+
GetContextHandlers(TypedSlotIndex.TargetedHandleFast),
|
|
2708
2692
|
ref message,
|
|
2709
2693
|
priority,
|
|
2710
2694
|
emissionId
|
|
2711
2695
|
);
|
|
2712
2696
|
RunHandlersWithContext(
|
|
2713
2697
|
ref target,
|
|
2714
|
-
|
|
2698
|
+
GetContextHandlers(TypedSlotIndex.TargetedHandleDefault),
|
|
2715
2699
|
ref message,
|
|
2716
2700
|
priority,
|
|
2717
2701
|
emissionId
|
|
@@ -2733,14 +2717,14 @@ namespace DxMessaging.Core
|
|
|
2733
2717
|
{
|
|
2734
2718
|
RunFastHandlers(
|
|
2735
2719
|
ref target,
|
|
2736
|
-
|
|
2720
|
+
GetPriorityHandlers(TypedSlotIndex.TargetedHandleWithoutContextFast),
|
|
2737
2721
|
ref message,
|
|
2738
2722
|
priority,
|
|
2739
2723
|
emissionId
|
|
2740
2724
|
);
|
|
2741
2725
|
RunHandlers(
|
|
2742
2726
|
ref target,
|
|
2743
|
-
|
|
2727
|
+
GetPriorityHandlers(TypedSlotIndex.TargetedHandleWithoutContext),
|
|
2744
2728
|
ref message,
|
|
2745
2729
|
priority,
|
|
2746
2730
|
emissionId
|
|
@@ -2762,14 +2746,14 @@ namespace DxMessaging.Core
|
|
|
2762
2746
|
{
|
|
2763
2747
|
RunFastHandlersWithContext(
|
|
2764
2748
|
ref source,
|
|
2765
|
-
|
|
2749
|
+
GetContextHandlers(TypedSlotIndex.BroadcastHandleFast),
|
|
2766
2750
|
ref message,
|
|
2767
2751
|
priority,
|
|
2768
2752
|
emissionId
|
|
2769
2753
|
);
|
|
2770
2754
|
RunHandlersWithContext(
|
|
2771
2755
|
ref source,
|
|
2772
|
-
|
|
2756
|
+
GetContextHandlers(TypedSlotIndex.BroadcastHandleDefault),
|
|
2773
2757
|
ref message,
|
|
2774
2758
|
priority,
|
|
2775
2759
|
emissionId
|
|
@@ -2791,14 +2775,14 @@ namespace DxMessaging.Core
|
|
|
2791
2775
|
{
|
|
2792
2776
|
RunFastHandlers(
|
|
2793
2777
|
ref source,
|
|
2794
|
-
|
|
2778
|
+
GetPriorityHandlers(TypedSlotIndex.BroadcastHandleWithoutContextFast),
|
|
2795
2779
|
ref message,
|
|
2796
2780
|
priority,
|
|
2797
2781
|
emissionId
|
|
2798
2782
|
);
|
|
2799
2783
|
RunHandlers(
|
|
2800
2784
|
ref source,
|
|
2801
|
-
|
|
2785
|
+
GetPriorityHandlers(TypedSlotIndex.BroadcastHandleWithoutContext),
|
|
2802
2786
|
ref message,
|
|
2803
2787
|
priority,
|
|
2804
2788
|
emissionId
|
|
@@ -2811,18 +2795,36 @@ namespace DxMessaging.Core
|
|
|
2811
2795
|
/// <param name="message">Message to emit.</param>
|
|
2812
2796
|
public void HandleGlobalUntargeted(ref IUntargetedMessage message, long emissionId)
|
|
2813
2797
|
{
|
|
2814
|
-
|
|
2815
|
-
|
|
2798
|
+
HandlerActionCache<FastHandler<IUntargetedMessage>> fastCache = GetGlobalCache<
|
|
2799
|
+
FastHandler<IUntargetedMessage>
|
|
2800
|
+
>(TypedGlobalSlotIndex.UntargetedFast);
|
|
2801
|
+
RunFastHandlers(fastCache, ref message, emissionId);
|
|
2802
|
+
HandlerActionCache<Action<IUntargetedMessage>> cache = GetGlobalCache<
|
|
2803
|
+
Action<IUntargetedMessage>
|
|
2804
|
+
>(TypedGlobalSlotIndex.UntargetedDefault);
|
|
2805
|
+
// Live-count fast path. Cross-handler in-flight snapshot
|
|
2806
|
+
// semantics do not apply to the global accept-all path: the
|
|
2807
|
+
// bus dispatch loop calls PrefreezeGlobalUntargetedForEmission
|
|
2808
|
+
// lazily per-entry inside InvokeGlobalUntargetedEntry, after
|
|
2809
|
+
// earlier-priority handlers have already run. A sibling
|
|
2810
|
+
// MessageHandler that removes this handler's entry mid-emit
|
|
2811
|
+
// drains cache.entries before the lazy prefreeze can capture
|
|
2812
|
+
// a snapshot, so cache.cache rebuilds from the now-empty
|
|
2813
|
+
// entries. Bailing on cache.entries.Count == 0 is therefore
|
|
2814
|
+
// equivalent to bailing after GetOrAddNewHandlerStack would
|
|
2815
|
+
// return an empty list, and is documented behavior for the
|
|
2816
|
+
// global path.
|
|
2817
|
+
if (cache?.entries is not { Count: > 0 })
|
|
2816
2818
|
{
|
|
2817
2819
|
return;
|
|
2818
2820
|
}
|
|
2819
2821
|
|
|
2820
2822
|
List<Action<IUntargetedMessage>> handlers = GetOrAddNewHandlerStack(
|
|
2821
|
-
|
|
2823
|
+
cache,
|
|
2822
2824
|
emissionId
|
|
2823
2825
|
);
|
|
2824
2826
|
int handlersCount = handlers.Count;
|
|
2825
|
-
for (int i = 0; i < handlersCount; ++i)
|
|
2827
|
+
for (int i = 0; i < handlersCount && i < handlers.Count; ++i)
|
|
2826
2828
|
{
|
|
2827
2829
|
handlers[i](message);
|
|
2828
2830
|
}
|
|
@@ -2839,19 +2841,29 @@ namespace DxMessaging.Core
|
|
|
2839
2841
|
long emissionId
|
|
2840
2842
|
)
|
|
2841
2843
|
{
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
|
|
2844
|
+
HandlerActionCache<FastHandlerWithContext<ITargetedMessage>> fastCache =
|
|
2845
|
+
GetGlobalCache<FastHandlerWithContext<ITargetedMessage>>(
|
|
2846
|
+
TypedGlobalSlotIndex.TargetedFast
|
|
2847
|
+
);
|
|
2848
|
+
RunFastHandlers(ref target, fastCache, ref message, emissionId);
|
|
2849
|
+
|
|
2850
|
+
HandlerActionCache<Action<InstanceId, ITargetedMessage>> cache = GetGlobalCache<
|
|
2851
|
+
Action<InstanceId, ITargetedMessage>
|
|
2852
|
+
>(TypedGlobalSlotIndex.TargetedDefault);
|
|
2853
|
+
// Live-count fast path. See comment in HandleGlobalUntargeted
|
|
2854
|
+
// for why the global accept-all path bails on
|
|
2855
|
+
// cache.entries.Count == 0 rather than reading the snapshot.
|
|
2856
|
+
if (cache?.entries is not { Count: > 0 })
|
|
2845
2857
|
{
|
|
2846
2858
|
return;
|
|
2847
2859
|
}
|
|
2848
2860
|
|
|
2849
2861
|
List<Action<InstanceId, ITargetedMessage>> handlers = GetOrAddNewHandlerStack(
|
|
2850
|
-
|
|
2862
|
+
cache,
|
|
2851
2863
|
emissionId
|
|
2852
2864
|
);
|
|
2853
2865
|
int handlersCount = handlers.Count;
|
|
2854
|
-
for (int i = 0; i < handlersCount; ++i)
|
|
2866
|
+
for (int i = 0; i < handlersCount && i < handlers.Count; ++i)
|
|
2855
2867
|
{
|
|
2856
2868
|
handlers[i](target, message);
|
|
2857
2869
|
}
|
|
@@ -2868,15 +2880,25 @@ namespace DxMessaging.Core
|
|
|
2868
2880
|
long emissionId
|
|
2869
2881
|
)
|
|
2870
2882
|
{
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
|
|
2883
|
+
HandlerActionCache<FastHandlerWithContext<IBroadcastMessage>> fastCache =
|
|
2884
|
+
GetGlobalCache<FastHandlerWithContext<IBroadcastMessage>>(
|
|
2885
|
+
TypedGlobalSlotIndex.BroadcastFast
|
|
2886
|
+
);
|
|
2887
|
+
RunFastHandlers(ref source, fastCache, ref message, emissionId);
|
|
2888
|
+
|
|
2889
|
+
HandlerActionCache<Action<InstanceId, IBroadcastMessage>> cache = GetGlobalCache<
|
|
2890
|
+
Action<InstanceId, IBroadcastMessage>
|
|
2891
|
+
>(TypedGlobalSlotIndex.BroadcastDefault);
|
|
2892
|
+
// Live-count fast path. See comment in HandleGlobalUntargeted
|
|
2893
|
+
// for why the global accept-all path bails on
|
|
2894
|
+
// cache.entries.Count == 0 rather than reading the snapshot.
|
|
2895
|
+
if (cache?.entries is not { Count: > 0 })
|
|
2874
2896
|
{
|
|
2875
2897
|
return;
|
|
2876
2898
|
}
|
|
2877
2899
|
|
|
2878
2900
|
List<Action<InstanceId, IBroadcastMessage>> handlers = GetOrAddNewHandlerStack(
|
|
2879
|
-
|
|
2901
|
+
cache,
|
|
2880
2902
|
emissionId
|
|
2881
2903
|
);
|
|
2882
2904
|
int handlersCount = handlers.Count;
|
|
@@ -2890,36 +2912,76 @@ namespace DxMessaging.Core
|
|
|
2890
2912
|
case 2:
|
|
2891
2913
|
{
|
|
2892
2914
|
handlers[0](source, message);
|
|
2915
|
+
if (handlers.Count < 2)
|
|
2916
|
+
{
|
|
2917
|
+
return;
|
|
2918
|
+
}
|
|
2893
2919
|
handlers[1](source, message);
|
|
2894
2920
|
return;
|
|
2895
2921
|
}
|
|
2896
2922
|
case 3:
|
|
2897
2923
|
{
|
|
2898
2924
|
handlers[0](source, message);
|
|
2925
|
+
if (handlers.Count < 2)
|
|
2926
|
+
{
|
|
2927
|
+
return;
|
|
2928
|
+
}
|
|
2899
2929
|
handlers[1](source, message);
|
|
2930
|
+
if (handlers.Count < 3)
|
|
2931
|
+
{
|
|
2932
|
+
return;
|
|
2933
|
+
}
|
|
2900
2934
|
handlers[2](source, message);
|
|
2901
2935
|
return;
|
|
2902
2936
|
}
|
|
2903
2937
|
case 4:
|
|
2904
2938
|
{
|
|
2905
2939
|
handlers[0](source, message);
|
|
2940
|
+
if (handlers.Count < 2)
|
|
2941
|
+
{
|
|
2942
|
+
return;
|
|
2943
|
+
}
|
|
2906
2944
|
handlers[1](source, message);
|
|
2945
|
+
if (handlers.Count < 3)
|
|
2946
|
+
{
|
|
2947
|
+
return;
|
|
2948
|
+
}
|
|
2907
2949
|
handlers[2](source, message);
|
|
2950
|
+
if (handlers.Count < 4)
|
|
2951
|
+
{
|
|
2952
|
+
return;
|
|
2953
|
+
}
|
|
2908
2954
|
handlers[3](source, message);
|
|
2909
2955
|
return;
|
|
2910
2956
|
}
|
|
2911
2957
|
case 5:
|
|
2912
2958
|
{
|
|
2913
2959
|
handlers[0](source, message);
|
|
2960
|
+
if (handlers.Count < 2)
|
|
2961
|
+
{
|
|
2962
|
+
return;
|
|
2963
|
+
}
|
|
2914
2964
|
handlers[1](source, message);
|
|
2965
|
+
if (handlers.Count < 3)
|
|
2966
|
+
{
|
|
2967
|
+
return;
|
|
2968
|
+
}
|
|
2915
2969
|
handlers[2](source, message);
|
|
2970
|
+
if (handlers.Count < 4)
|
|
2971
|
+
{
|
|
2972
|
+
return;
|
|
2973
|
+
}
|
|
2916
2974
|
handlers[3](source, message);
|
|
2975
|
+
if (handlers.Count < 5)
|
|
2976
|
+
{
|
|
2977
|
+
return;
|
|
2978
|
+
}
|
|
2917
2979
|
handlers[4](source, message);
|
|
2918
2980
|
return;
|
|
2919
2981
|
}
|
|
2920
2982
|
}
|
|
2921
2983
|
|
|
2922
|
-
for (int i = 0; i < handlersCount; ++i)
|
|
2984
|
+
for (int i = 0; i < handlersCount && i < handlers.Count; ++i)
|
|
2923
2985
|
{
|
|
2924
2986
|
handlers[i](source, message);
|
|
2925
2987
|
}
|
|
@@ -2934,12 +2996,17 @@ namespace DxMessaging.Core
|
|
|
2934
2996
|
public void HandleUntargetedPostProcessing(ref T message, int priority, long emissionId)
|
|
2935
2997
|
{
|
|
2936
2998
|
RunFastHandlers(
|
|
2937
|
-
|
|
2999
|
+
GetPriorityHandlers(TypedSlotIndex.UntargetedPostProcessFast),
|
|
3000
|
+
ref message,
|
|
3001
|
+
priority,
|
|
3002
|
+
emissionId
|
|
3003
|
+
);
|
|
3004
|
+
RunHandlers(
|
|
3005
|
+
GetPriorityHandlers(TypedSlotIndex.UntargetedPostProcessDefault),
|
|
2938
3006
|
ref message,
|
|
2939
3007
|
priority,
|
|
2940
3008
|
emissionId
|
|
2941
3009
|
);
|
|
2942
|
-
RunHandlers(_untargetedPostProcessingHandlers, ref message, priority, emissionId);
|
|
2943
3010
|
}
|
|
2944
3011
|
|
|
2945
3012
|
/// <summary>
|
|
@@ -2958,14 +3025,14 @@ namespace DxMessaging.Core
|
|
|
2958
3025
|
{
|
|
2959
3026
|
RunFastHandlersWithContext(
|
|
2960
3027
|
ref target,
|
|
2961
|
-
|
|
3028
|
+
GetContextHandlers(TypedSlotIndex.TargetedPostProcessFast),
|
|
2962
3029
|
ref message,
|
|
2963
3030
|
priority,
|
|
2964
3031
|
emissionId
|
|
2965
3032
|
);
|
|
2966
3033
|
RunHandlersWithContext(
|
|
2967
3034
|
ref target,
|
|
2968
|
-
|
|
3035
|
+
GetContextHandlers(TypedSlotIndex.TargetedPostProcessDefault),
|
|
2969
3036
|
ref message,
|
|
2970
3037
|
priority,
|
|
2971
3038
|
emissionId
|
|
@@ -2988,14 +3055,14 @@ namespace DxMessaging.Core
|
|
|
2988
3055
|
{
|
|
2989
3056
|
RunFastHandlersWithContext(
|
|
2990
3057
|
ref target,
|
|
2991
|
-
|
|
3058
|
+
GetPriorityHandlers(TypedSlotIndex.TargetedPostProcessWithoutContextFast),
|
|
2992
3059
|
ref message,
|
|
2993
3060
|
priority,
|
|
2994
3061
|
emissionId
|
|
2995
3062
|
);
|
|
2996
3063
|
RunHandlers(
|
|
2997
3064
|
ref target,
|
|
2998
|
-
|
|
3065
|
+
GetPriorityHandlers(TypedSlotIndex.TargetedPostProcessWithoutContext),
|
|
2999
3066
|
ref message,
|
|
3000
3067
|
priority,
|
|
3001
3068
|
emissionId
|
|
@@ -3018,14 +3085,14 @@ namespace DxMessaging.Core
|
|
|
3018
3085
|
{
|
|
3019
3086
|
RunFastHandlersWithContext(
|
|
3020
3087
|
ref source,
|
|
3021
|
-
|
|
3088
|
+
GetContextHandlers(TypedSlotIndex.BroadcastPostProcessFast),
|
|
3022
3089
|
ref message,
|
|
3023
3090
|
priority,
|
|
3024
3091
|
emissionId
|
|
3025
3092
|
);
|
|
3026
3093
|
RunHandlersWithContext(
|
|
3027
3094
|
ref source,
|
|
3028
|
-
|
|
3095
|
+
GetContextHandlers(TypedSlotIndex.BroadcastPostProcessDefault),
|
|
3029
3096
|
ref message,
|
|
3030
3097
|
priority,
|
|
3031
3098
|
emissionId
|
|
@@ -3048,14 +3115,14 @@ namespace DxMessaging.Core
|
|
|
3048
3115
|
{
|
|
3049
3116
|
RunFastHandlersWithContext(
|
|
3050
3117
|
ref source,
|
|
3051
|
-
|
|
3118
|
+
GetPriorityHandlers(TypedSlotIndex.BroadcastPostProcessWithoutContextFast),
|
|
3052
3119
|
ref message,
|
|
3053
3120
|
priority,
|
|
3054
3121
|
emissionId
|
|
3055
3122
|
);
|
|
3056
3123
|
RunHandlers(
|
|
3057
3124
|
ref source,
|
|
3058
|
-
|
|
3125
|
+
GetPriorityHandlers(TypedSlotIndex.BroadcastPostProcessWithoutContext),
|
|
3059
3126
|
ref message,
|
|
3060
3127
|
priority,
|
|
3061
3128
|
emissionId
|
|
@@ -3076,17 +3143,22 @@ namespace DxMessaging.Core
|
|
|
3076
3143
|
Action<T> handler,
|
|
3077
3144
|
Action deregistration,
|
|
3078
3145
|
int priority,
|
|
3079
|
-
|
|
3146
|
+
IMessageBus messageBus
|
|
3080
3147
|
)
|
|
3081
3148
|
{
|
|
3082
|
-
|
|
3149
|
+
// Adapt the AUGMENTED handler to FastHandler form exactly once,
|
|
3150
|
+
// at registration time, so bus-side flat snapshot rebuilds
|
|
3151
|
+
// resolve default registrations without allocating closures.
|
|
3152
|
+
FastHandler<T> flatInvoker = (ref T message) => handler(message);
|
|
3153
|
+
return AddHandlerPreservingPriorityKey(
|
|
3083
3154
|
target,
|
|
3084
|
-
|
|
3155
|
+
GetOrCreateContextHandlers(TypedSlotIndex.TargetedHandleDefault),
|
|
3085
3156
|
originalHandler,
|
|
3086
3157
|
handler,
|
|
3087
3158
|
deregistration,
|
|
3088
3159
|
priority,
|
|
3089
|
-
|
|
3160
|
+
messageBus,
|
|
3161
|
+
flatInvoker
|
|
3090
3162
|
);
|
|
3091
3163
|
}
|
|
3092
3164
|
|
|
@@ -3104,17 +3176,17 @@ namespace DxMessaging.Core
|
|
|
3104
3176
|
FastHandler<T> handler,
|
|
3105
3177
|
Action deregistration,
|
|
3106
3178
|
int priority,
|
|
3107
|
-
|
|
3179
|
+
IMessageBus messageBus
|
|
3108
3180
|
)
|
|
3109
3181
|
{
|
|
3110
|
-
return
|
|
3182
|
+
return AddHandlerPreservingPriorityKey(
|
|
3111
3183
|
target,
|
|
3112
|
-
|
|
3184
|
+
GetOrCreateContextHandlers(TypedSlotIndex.TargetedHandleFast),
|
|
3113
3185
|
originalHandler,
|
|
3114
3186
|
handler,
|
|
3115
3187
|
deregistration,
|
|
3116
3188
|
priority,
|
|
3117
|
-
|
|
3189
|
+
messageBus
|
|
3118
3190
|
);
|
|
3119
3191
|
}
|
|
3120
3192
|
|
|
@@ -3130,16 +3202,26 @@ namespace DxMessaging.Core
|
|
|
3130
3202
|
Action<InstanceId, T> handler,
|
|
3131
3203
|
Action deregistration,
|
|
3132
3204
|
int priority,
|
|
3133
|
-
|
|
3205
|
+
IMessageBus messageBus
|
|
3134
3206
|
)
|
|
3135
3207
|
{
|
|
3208
|
+
// Adapt the AUGMENTED handler to FastHandlerWithContext form
|
|
3209
|
+
// exactly once, at registration time, so bus-side flat snapshot
|
|
3210
|
+
// rebuilds resolve default registrations without allocating
|
|
3211
|
+
// closures.
|
|
3212
|
+
FastHandlerWithContext<T> flatInvoker = (ref InstanceId context, ref T message) =>
|
|
3213
|
+
handler(context, message);
|
|
3136
3214
|
return AddHandlerPreservingPriorityKey(
|
|
3137
|
-
|
|
3215
|
+
GetOrCreatePriorityHandlers(
|
|
3216
|
+
TypedSlotIndex.TargetedHandleWithoutContext,
|
|
3217
|
+
requiresContext: false
|
|
3218
|
+
),
|
|
3138
3219
|
originalHandler,
|
|
3139
3220
|
handler,
|
|
3140
3221
|
deregistration,
|
|
3141
3222
|
priority,
|
|
3142
|
-
|
|
3223
|
+
messageBus,
|
|
3224
|
+
flatInvoker
|
|
3143
3225
|
);
|
|
3144
3226
|
}
|
|
3145
3227
|
|
|
@@ -3155,16 +3237,19 @@ namespace DxMessaging.Core
|
|
|
3155
3237
|
FastHandlerWithContext<T> handler,
|
|
3156
3238
|
Action deregistration,
|
|
3157
3239
|
int priority,
|
|
3158
|
-
|
|
3240
|
+
IMessageBus messageBus
|
|
3159
3241
|
)
|
|
3160
3242
|
{
|
|
3161
3243
|
return AddHandlerPreservingPriorityKey(
|
|
3162
|
-
|
|
3244
|
+
GetOrCreatePriorityHandlers(
|
|
3245
|
+
TypedSlotIndex.TargetedHandleWithoutContextFast,
|
|
3246
|
+
requiresContext: false
|
|
3247
|
+
),
|
|
3163
3248
|
originalHandler,
|
|
3164
3249
|
handler,
|
|
3165
3250
|
deregistration,
|
|
3166
3251
|
priority,
|
|
3167
|
-
|
|
3252
|
+
messageBus
|
|
3168
3253
|
);
|
|
3169
3254
|
}
|
|
3170
3255
|
|
|
@@ -3180,16 +3265,24 @@ namespace DxMessaging.Core
|
|
|
3180
3265
|
Action<T> handler,
|
|
3181
3266
|
Action deregistration,
|
|
3182
3267
|
int priority,
|
|
3183
|
-
|
|
3268
|
+
IMessageBus messageBus
|
|
3184
3269
|
)
|
|
3185
3270
|
{
|
|
3186
|
-
|
|
3187
|
-
|
|
3271
|
+
// Adapt the AUGMENTED handler to FastHandler form exactly once,
|
|
3272
|
+
// at registration time, so bus-side flat snapshot rebuilds
|
|
3273
|
+
// resolve default registrations without allocating closures.
|
|
3274
|
+
FastHandler<T> flatInvoker = (ref T message) => handler(message);
|
|
3275
|
+
return AddHandlerPreservingPriorityKey(
|
|
3276
|
+
GetOrCreatePriorityHandlers(
|
|
3277
|
+
TypedSlotIndex.UntargetedHandleDefault,
|
|
3278
|
+
requiresContext: false
|
|
3279
|
+
),
|
|
3188
3280
|
originalHandler,
|
|
3189
3281
|
handler,
|
|
3190
3282
|
deregistration,
|
|
3191
3283
|
priority,
|
|
3192
|
-
|
|
3284
|
+
messageBus,
|
|
3285
|
+
flatInvoker
|
|
3193
3286
|
);
|
|
3194
3287
|
}
|
|
3195
3288
|
|
|
@@ -3205,16 +3298,19 @@ namespace DxMessaging.Core
|
|
|
3205
3298
|
FastHandler<T> handler,
|
|
3206
3299
|
Action deregistration,
|
|
3207
3300
|
int priority,
|
|
3208
|
-
|
|
3301
|
+
IMessageBus messageBus
|
|
3209
3302
|
)
|
|
3210
3303
|
{
|
|
3211
|
-
return
|
|
3212
|
-
|
|
3304
|
+
return AddHandlerPreservingPriorityKey(
|
|
3305
|
+
GetOrCreatePriorityHandlers(
|
|
3306
|
+
TypedSlotIndex.UntargetedHandleFast,
|
|
3307
|
+
requiresContext: false
|
|
3308
|
+
),
|
|
3213
3309
|
originalHandler,
|
|
3214
3310
|
handler,
|
|
3215
3311
|
deregistration,
|
|
3216
3312
|
priority,
|
|
3217
|
-
|
|
3313
|
+
messageBus
|
|
3218
3314
|
);
|
|
3219
3315
|
}
|
|
3220
3316
|
|
|
@@ -3232,17 +3328,22 @@ namespace DxMessaging.Core
|
|
|
3232
3328
|
Action<T> handler,
|
|
3233
3329
|
Action deregistration,
|
|
3234
3330
|
int priority,
|
|
3235
|
-
|
|
3331
|
+
IMessageBus messageBus
|
|
3236
3332
|
)
|
|
3237
3333
|
{
|
|
3238
|
-
|
|
3334
|
+
// Adapt the AUGMENTED handler to FastHandler form exactly once,
|
|
3335
|
+
// at registration time, so bus-side flat snapshot rebuilds
|
|
3336
|
+
// resolve default registrations without allocating closures.
|
|
3337
|
+
FastHandler<T> flatInvoker = (ref T message) => handler(message);
|
|
3338
|
+
return AddHandlerPreservingPriorityKey(
|
|
3239
3339
|
source,
|
|
3240
|
-
|
|
3340
|
+
GetOrCreateContextHandlers(TypedSlotIndex.BroadcastHandleDefault),
|
|
3241
3341
|
originalHandler,
|
|
3242
3342
|
handler,
|
|
3243
3343
|
deregistration,
|
|
3244
3344
|
priority,
|
|
3245
|
-
|
|
3345
|
+
messageBus,
|
|
3346
|
+
flatInvoker
|
|
3246
3347
|
);
|
|
3247
3348
|
}
|
|
3248
3349
|
|
|
@@ -3260,17 +3361,17 @@ namespace DxMessaging.Core
|
|
|
3260
3361
|
FastHandler<T> handler,
|
|
3261
3362
|
Action deregistration,
|
|
3262
3363
|
int priority,
|
|
3263
|
-
|
|
3364
|
+
IMessageBus messageBus
|
|
3264
3365
|
)
|
|
3265
3366
|
{
|
|
3266
|
-
return
|
|
3367
|
+
return AddHandlerPreservingPriorityKey(
|
|
3267
3368
|
source,
|
|
3268
|
-
|
|
3369
|
+
GetOrCreateContextHandlers(TypedSlotIndex.BroadcastHandleFast),
|
|
3269
3370
|
originalHandler,
|
|
3270
3371
|
handler,
|
|
3271
3372
|
deregistration,
|
|
3272
3373
|
priority,
|
|
3273
|
-
|
|
3374
|
+
messageBus
|
|
3274
3375
|
);
|
|
3275
3376
|
}
|
|
3276
3377
|
|
|
@@ -3286,17 +3387,27 @@ namespace DxMessaging.Core
|
|
|
3286
3387
|
Action<InstanceId, T> handler,
|
|
3287
3388
|
Action deregistration,
|
|
3288
3389
|
int priority,
|
|
3289
|
-
|
|
3390
|
+
IMessageBus messageBus
|
|
3290
3391
|
)
|
|
3291
3392
|
{
|
|
3393
|
+
// Adapt the AUGMENTED handler to FastHandlerWithContext form
|
|
3394
|
+
// exactly once, at registration time, so bus-side flat snapshot
|
|
3395
|
+
// rebuilds resolve default registrations without allocating
|
|
3396
|
+
// closures.
|
|
3397
|
+
FastHandlerWithContext<T> flatInvoker = (ref InstanceId context, ref T message) =>
|
|
3398
|
+
handler(context, message);
|
|
3292
3399
|
// Preserve the priority bucket during the current emission so frozen snapshots remain valid
|
|
3293
3400
|
return AddHandlerPreservingPriorityKey(
|
|
3294
|
-
|
|
3401
|
+
GetOrCreatePriorityHandlers(
|
|
3402
|
+
TypedSlotIndex.BroadcastHandleWithoutContext,
|
|
3403
|
+
requiresContext: false
|
|
3404
|
+
),
|
|
3295
3405
|
originalHandler,
|
|
3296
3406
|
handler,
|
|
3297
3407
|
deregistration,
|
|
3298
3408
|
priority,
|
|
3299
|
-
|
|
3409
|
+
messageBus,
|
|
3410
|
+
flatInvoker
|
|
3300
3411
|
);
|
|
3301
3412
|
}
|
|
3302
3413
|
|
|
@@ -3312,17 +3423,20 @@ namespace DxMessaging.Core
|
|
|
3312
3423
|
FastHandlerWithContext<T> handler,
|
|
3313
3424
|
Action deregistration,
|
|
3314
3425
|
int priority,
|
|
3315
|
-
|
|
3426
|
+
IMessageBus messageBus
|
|
3316
3427
|
)
|
|
3317
3428
|
{
|
|
3318
3429
|
// Preserve the priority bucket during the current emission so frozen snapshots remain valid
|
|
3319
3430
|
return AddHandlerPreservingPriorityKey(
|
|
3320
|
-
|
|
3431
|
+
GetOrCreatePriorityHandlers(
|
|
3432
|
+
TypedSlotIndex.BroadcastHandleWithoutContextFast,
|
|
3433
|
+
requiresContext: false
|
|
3434
|
+
),
|
|
3321
3435
|
originalHandler,
|
|
3322
3436
|
handler,
|
|
3323
3437
|
deregistration,
|
|
3324
3438
|
priority,
|
|
3325
|
-
|
|
3439
|
+
messageBus
|
|
3326
3440
|
);
|
|
3327
3441
|
}
|
|
3328
3442
|
|
|
@@ -3335,14 +3449,16 @@ namespace DxMessaging.Core
|
|
|
3335
3449
|
public Action AddGlobalUntargetedHandler(
|
|
3336
3450
|
Action<IUntargetedMessage> originalHandler,
|
|
3337
3451
|
Action<IUntargetedMessage> handler,
|
|
3338
|
-
Action deregistration
|
|
3452
|
+
Action deregistration,
|
|
3453
|
+
IMessageBus messageBus
|
|
3339
3454
|
)
|
|
3340
3455
|
{
|
|
3341
3456
|
return AddHandler(
|
|
3342
|
-
|
|
3457
|
+
GetOrCreateGlobalSlot(TypedGlobalSlotIndex.UntargetedDefault),
|
|
3343
3458
|
originalHandler,
|
|
3344
3459
|
handler,
|
|
3345
|
-
deregistration
|
|
3460
|
+
deregistration,
|
|
3461
|
+
messageBus
|
|
3346
3462
|
);
|
|
3347
3463
|
}
|
|
3348
3464
|
|
|
@@ -3355,14 +3471,16 @@ namespace DxMessaging.Core
|
|
|
3355
3471
|
public Action AddGlobalUntargetedHandler(
|
|
3356
3472
|
FastHandler<IUntargetedMessage> originalHandler,
|
|
3357
3473
|
FastHandler<IUntargetedMessage> handler,
|
|
3358
|
-
Action deregistration
|
|
3474
|
+
Action deregistration,
|
|
3475
|
+
IMessageBus messageBus
|
|
3359
3476
|
)
|
|
3360
3477
|
{
|
|
3361
3478
|
return AddHandler(
|
|
3362
|
-
|
|
3479
|
+
GetOrCreateGlobalSlot(TypedGlobalSlotIndex.UntargetedFast),
|
|
3363
3480
|
originalHandler,
|
|
3364
3481
|
handler,
|
|
3365
|
-
deregistration
|
|
3482
|
+
deregistration,
|
|
3483
|
+
messageBus
|
|
3366
3484
|
);
|
|
3367
3485
|
}
|
|
3368
3486
|
|
|
@@ -3375,14 +3493,16 @@ namespace DxMessaging.Core
|
|
|
3375
3493
|
public Action AddGlobalTargetedHandler(
|
|
3376
3494
|
Action<InstanceId, ITargetedMessage> originalHandler,
|
|
3377
3495
|
Action<InstanceId, ITargetedMessage> handler,
|
|
3378
|
-
Action deregistration
|
|
3496
|
+
Action deregistration,
|
|
3497
|
+
IMessageBus messageBus
|
|
3379
3498
|
)
|
|
3380
3499
|
{
|
|
3381
3500
|
return AddHandler(
|
|
3382
|
-
|
|
3501
|
+
GetOrCreateGlobalSlot(TypedGlobalSlotIndex.TargetedDefault),
|
|
3383
3502
|
originalHandler,
|
|
3384
3503
|
handler,
|
|
3385
|
-
deregistration
|
|
3504
|
+
deregistration,
|
|
3505
|
+
messageBus
|
|
3386
3506
|
);
|
|
3387
3507
|
}
|
|
3388
3508
|
|
|
@@ -3395,14 +3515,16 @@ namespace DxMessaging.Core
|
|
|
3395
3515
|
public Action AddGlobalTargetedHandler(
|
|
3396
3516
|
FastHandlerWithContext<ITargetedMessage> originalHandler,
|
|
3397
3517
|
FastHandlerWithContext<ITargetedMessage> handler,
|
|
3398
|
-
Action deregistration
|
|
3518
|
+
Action deregistration,
|
|
3519
|
+
IMessageBus messageBus
|
|
3399
3520
|
)
|
|
3400
3521
|
{
|
|
3401
3522
|
return AddHandler(
|
|
3402
|
-
|
|
3523
|
+
GetOrCreateGlobalSlot(TypedGlobalSlotIndex.TargetedFast),
|
|
3403
3524
|
originalHandler,
|
|
3404
3525
|
handler,
|
|
3405
|
-
deregistration
|
|
3526
|
+
deregistration,
|
|
3527
|
+
messageBus
|
|
3406
3528
|
);
|
|
3407
3529
|
}
|
|
3408
3530
|
|
|
@@ -3415,14 +3537,16 @@ namespace DxMessaging.Core
|
|
|
3415
3537
|
public Action AddGlobalBroadcastHandler(
|
|
3416
3538
|
Action<InstanceId, IBroadcastMessage> originalHandler,
|
|
3417
3539
|
Action<InstanceId, IBroadcastMessage> handler,
|
|
3418
|
-
Action deregistration
|
|
3540
|
+
Action deregistration,
|
|
3541
|
+
IMessageBus messageBus
|
|
3419
3542
|
)
|
|
3420
3543
|
{
|
|
3421
3544
|
return AddHandler(
|
|
3422
|
-
|
|
3545
|
+
GetOrCreateGlobalSlot(TypedGlobalSlotIndex.BroadcastDefault),
|
|
3423
3546
|
originalHandler,
|
|
3424
3547
|
handler,
|
|
3425
|
-
deregistration
|
|
3548
|
+
deregistration,
|
|
3549
|
+
messageBus
|
|
3426
3550
|
);
|
|
3427
3551
|
}
|
|
3428
3552
|
|
|
@@ -3435,14 +3559,16 @@ namespace DxMessaging.Core
|
|
|
3435
3559
|
public Action AddGlobalBroadcastHandler(
|
|
3436
3560
|
FastHandlerWithContext<IBroadcastMessage> originalHandler,
|
|
3437
3561
|
FastHandlerWithContext<IBroadcastMessage> handler,
|
|
3438
|
-
Action deregistration
|
|
3562
|
+
Action deregistration,
|
|
3563
|
+
IMessageBus messageBus
|
|
3439
3564
|
)
|
|
3440
3565
|
{
|
|
3441
3566
|
return AddHandler(
|
|
3442
|
-
|
|
3567
|
+
GetOrCreateGlobalSlot(TypedGlobalSlotIndex.BroadcastFast),
|
|
3443
3568
|
originalHandler,
|
|
3444
3569
|
handler,
|
|
3445
|
-
deregistration
|
|
3570
|
+
deregistration,
|
|
3571
|
+
messageBus
|
|
3446
3572
|
);
|
|
3447
3573
|
}
|
|
3448
3574
|
|
|
@@ -3458,16 +3584,24 @@ namespace DxMessaging.Core
|
|
|
3458
3584
|
Action<T> handler,
|
|
3459
3585
|
Action deregistration,
|
|
3460
3586
|
int priority,
|
|
3461
|
-
|
|
3587
|
+
IMessageBus messageBus
|
|
3462
3588
|
)
|
|
3463
3589
|
{
|
|
3590
|
+
// Adapt the AUGMENTED handler to FastHandler form exactly once,
|
|
3591
|
+
// at registration time, so bus-side flat snapshot rebuilds
|
|
3592
|
+
// resolve default registrations without allocating closures.
|
|
3593
|
+
FastHandler<T> flatInvoker = (ref T message) => handler(message);
|
|
3464
3594
|
return AddHandlerPreservingPriorityKey(
|
|
3465
|
-
|
|
3595
|
+
GetOrCreatePriorityHandlers(
|
|
3596
|
+
TypedSlotIndex.UntargetedPostProcessDefault,
|
|
3597
|
+
requiresContext: false
|
|
3598
|
+
),
|
|
3466
3599
|
originalHandler,
|
|
3467
3600
|
handler,
|
|
3468
3601
|
deregistration,
|
|
3469
3602
|
priority,
|
|
3470
|
-
|
|
3603
|
+
messageBus,
|
|
3604
|
+
flatInvoker
|
|
3471
3605
|
);
|
|
3472
3606
|
}
|
|
3473
3607
|
|
|
@@ -3483,16 +3617,19 @@ namespace DxMessaging.Core
|
|
|
3483
3617
|
FastHandler<T> handler,
|
|
3484
3618
|
Action deregistration,
|
|
3485
3619
|
int priority,
|
|
3486
|
-
|
|
3620
|
+
IMessageBus messageBus
|
|
3487
3621
|
)
|
|
3488
3622
|
{
|
|
3489
3623
|
return AddHandlerPreservingPriorityKey(
|
|
3490
|
-
|
|
3624
|
+
GetOrCreatePriorityHandlers(
|
|
3625
|
+
TypedSlotIndex.UntargetedPostProcessFast,
|
|
3626
|
+
requiresContext: false
|
|
3627
|
+
),
|
|
3491
3628
|
originalHandler,
|
|
3492
3629
|
handler,
|
|
3493
3630
|
deregistration,
|
|
3494
3631
|
priority,
|
|
3495
|
-
|
|
3632
|
+
messageBus
|
|
3496
3633
|
);
|
|
3497
3634
|
}
|
|
3498
3635
|
|
|
@@ -3510,17 +3647,22 @@ namespace DxMessaging.Core
|
|
|
3510
3647
|
Action<T> handler,
|
|
3511
3648
|
Action deregistration,
|
|
3512
3649
|
int priority,
|
|
3513
|
-
|
|
3650
|
+
IMessageBus messageBus
|
|
3514
3651
|
)
|
|
3515
3652
|
{
|
|
3653
|
+
// Adapt the AUGMENTED handler to FastHandler form exactly once,
|
|
3654
|
+
// at registration time, so bus-side flat snapshot rebuilds
|
|
3655
|
+
// resolve default registrations without allocating closures.
|
|
3656
|
+
FastHandler<T> flatInvoker = (ref T message) => handler(message);
|
|
3516
3657
|
return AddHandlerPreservingPriorityKey(
|
|
3517
3658
|
target,
|
|
3518
|
-
|
|
3659
|
+
GetOrCreateContextHandlers(TypedSlotIndex.TargetedPostProcessDefault),
|
|
3519
3660
|
originalHandler,
|
|
3520
3661
|
handler,
|
|
3521
3662
|
deregistration,
|
|
3522
3663
|
priority,
|
|
3523
|
-
|
|
3664
|
+
messageBus,
|
|
3665
|
+
flatInvoker
|
|
3524
3666
|
);
|
|
3525
3667
|
}
|
|
3526
3668
|
|
|
@@ -3538,17 +3680,17 @@ namespace DxMessaging.Core
|
|
|
3538
3680
|
FastHandler<T> handler,
|
|
3539
3681
|
Action deregistration,
|
|
3540
3682
|
int priority,
|
|
3541
|
-
|
|
3683
|
+
IMessageBus messageBus
|
|
3542
3684
|
)
|
|
3543
3685
|
{
|
|
3544
3686
|
return AddHandlerPreservingPriorityKey(
|
|
3545
3687
|
target,
|
|
3546
|
-
|
|
3688
|
+
GetOrCreateContextHandlers(TypedSlotIndex.TargetedPostProcessFast),
|
|
3547
3689
|
originalHandler,
|
|
3548
3690
|
handler,
|
|
3549
3691
|
deregistration,
|
|
3550
3692
|
priority,
|
|
3551
|
-
|
|
3693
|
+
messageBus
|
|
3552
3694
|
);
|
|
3553
3695
|
}
|
|
3554
3696
|
|
|
@@ -3564,16 +3706,26 @@ namespace DxMessaging.Core
|
|
|
3564
3706
|
Action<InstanceId, T> handler,
|
|
3565
3707
|
Action deregistration,
|
|
3566
3708
|
int priority,
|
|
3567
|
-
|
|
3709
|
+
IMessageBus messageBus
|
|
3568
3710
|
)
|
|
3569
3711
|
{
|
|
3712
|
+
// Adapt the AUGMENTED handler to FastHandlerWithContext form
|
|
3713
|
+
// exactly once, at registration time, so bus-side flat snapshot
|
|
3714
|
+
// rebuilds resolve default registrations without allocating
|
|
3715
|
+
// closures.
|
|
3716
|
+
FastHandlerWithContext<T> flatInvoker = (ref InstanceId context, ref T message) =>
|
|
3717
|
+
handler(context, message);
|
|
3570
3718
|
return AddHandlerPreservingPriorityKey(
|
|
3571
|
-
|
|
3719
|
+
GetOrCreatePriorityHandlers(
|
|
3720
|
+
TypedSlotIndex.TargetedPostProcessWithoutContext,
|
|
3721
|
+
requiresContext: false
|
|
3722
|
+
),
|
|
3572
3723
|
originalHandler,
|
|
3573
3724
|
handler,
|
|
3574
3725
|
deregistration,
|
|
3575
3726
|
priority,
|
|
3576
|
-
|
|
3727
|
+
messageBus,
|
|
3728
|
+
flatInvoker
|
|
3577
3729
|
);
|
|
3578
3730
|
}
|
|
3579
3731
|
|
|
@@ -3589,16 +3741,19 @@ namespace DxMessaging.Core
|
|
|
3589
3741
|
FastHandlerWithContext<T> handler,
|
|
3590
3742
|
Action deregistration,
|
|
3591
3743
|
int priority,
|
|
3592
|
-
|
|
3744
|
+
IMessageBus messageBus
|
|
3593
3745
|
)
|
|
3594
3746
|
{
|
|
3595
3747
|
return AddHandlerPreservingPriorityKey(
|
|
3596
|
-
|
|
3748
|
+
GetOrCreatePriorityHandlers(
|
|
3749
|
+
TypedSlotIndex.TargetedPostProcessWithoutContextFast,
|
|
3750
|
+
requiresContext: false
|
|
3751
|
+
),
|
|
3597
3752
|
originalHandler,
|
|
3598
3753
|
handler,
|
|
3599
3754
|
deregistration,
|
|
3600
3755
|
priority,
|
|
3601
|
-
|
|
3756
|
+
messageBus
|
|
3602
3757
|
);
|
|
3603
3758
|
}
|
|
3604
3759
|
|
|
@@ -3616,17 +3771,22 @@ namespace DxMessaging.Core
|
|
|
3616
3771
|
Action<T> handler,
|
|
3617
3772
|
Action deregistration,
|
|
3618
3773
|
int priority,
|
|
3619
|
-
|
|
3774
|
+
IMessageBus messageBus
|
|
3620
3775
|
)
|
|
3621
3776
|
{
|
|
3777
|
+
// Adapt the AUGMENTED handler to FastHandler form exactly once,
|
|
3778
|
+
// at registration time, so bus-side flat snapshot rebuilds
|
|
3779
|
+
// resolve default registrations without allocating closures.
|
|
3780
|
+
FastHandler<T> flatInvoker = (ref T message) => handler(message);
|
|
3622
3781
|
return AddHandlerPreservingPriorityKey(
|
|
3623
3782
|
source,
|
|
3624
|
-
|
|
3783
|
+
GetOrCreateContextHandlers(TypedSlotIndex.BroadcastPostProcessDefault),
|
|
3625
3784
|
originalHandler,
|
|
3626
3785
|
handler,
|
|
3627
3786
|
deregistration,
|
|
3628
3787
|
priority,
|
|
3629
|
-
|
|
3788
|
+
messageBus,
|
|
3789
|
+
flatInvoker
|
|
3630
3790
|
);
|
|
3631
3791
|
}
|
|
3632
3792
|
|
|
@@ -3644,17 +3804,17 @@ namespace DxMessaging.Core
|
|
|
3644
3804
|
FastHandler<T> handler,
|
|
3645
3805
|
Action deregistration,
|
|
3646
3806
|
int priority,
|
|
3647
|
-
|
|
3807
|
+
IMessageBus messageBus
|
|
3648
3808
|
)
|
|
3649
3809
|
{
|
|
3650
3810
|
return AddHandlerPreservingPriorityKey(
|
|
3651
3811
|
source,
|
|
3652
|
-
|
|
3812
|
+
GetOrCreateContextHandlers(TypedSlotIndex.BroadcastPostProcessFast),
|
|
3653
3813
|
originalHandler,
|
|
3654
3814
|
handler,
|
|
3655
3815
|
deregistration,
|
|
3656
3816
|
priority,
|
|
3657
|
-
|
|
3817
|
+
messageBus
|
|
3658
3818
|
);
|
|
3659
3819
|
}
|
|
3660
3820
|
|
|
@@ -3670,16 +3830,26 @@ namespace DxMessaging.Core
|
|
|
3670
3830
|
Action<InstanceId, T> handler,
|
|
3671
3831
|
Action deregistration,
|
|
3672
3832
|
int priority,
|
|
3673
|
-
|
|
3833
|
+
IMessageBus messageBus
|
|
3674
3834
|
)
|
|
3675
3835
|
{
|
|
3836
|
+
// Adapt the AUGMENTED handler to FastHandlerWithContext form
|
|
3837
|
+
// exactly once, at registration time, so bus-side flat snapshot
|
|
3838
|
+
// rebuilds resolve default registrations without allocating
|
|
3839
|
+
// closures.
|
|
3840
|
+
FastHandlerWithContext<T> flatInvoker = (ref InstanceId context, ref T message) =>
|
|
3841
|
+
handler(context, message);
|
|
3676
3842
|
return AddHandlerPreservingPriorityKey(
|
|
3677
|
-
|
|
3843
|
+
GetOrCreatePriorityHandlers(
|
|
3844
|
+
TypedSlotIndex.BroadcastPostProcessWithoutContext,
|
|
3845
|
+
requiresContext: false
|
|
3846
|
+
),
|
|
3678
3847
|
originalHandler,
|
|
3679
3848
|
handler,
|
|
3680
3849
|
deregistration,
|
|
3681
3850
|
priority,
|
|
3682
|
-
|
|
3851
|
+
messageBus,
|
|
3852
|
+
flatInvoker
|
|
3683
3853
|
);
|
|
3684
3854
|
}
|
|
3685
3855
|
|
|
@@ -3695,20 +3865,204 @@ namespace DxMessaging.Core
|
|
|
3695
3865
|
FastHandlerWithContext<T> handler,
|
|
3696
3866
|
Action deregistration,
|
|
3697
3867
|
int priority,
|
|
3698
|
-
|
|
3868
|
+
IMessageBus messageBus
|
|
3699
3869
|
)
|
|
3700
3870
|
{
|
|
3701
3871
|
return AddHandlerPreservingPriorityKey(
|
|
3702
|
-
|
|
3872
|
+
GetOrCreatePriorityHandlers(
|
|
3873
|
+
TypedSlotIndex.BroadcastPostProcessWithoutContextFast,
|
|
3874
|
+
requiresContext: false
|
|
3875
|
+
),
|
|
3703
3876
|
originalHandler,
|
|
3704
3877
|
handler,
|
|
3705
3878
|
deregistration,
|
|
3706
3879
|
priority,
|
|
3707
|
-
|
|
3880
|
+
messageBus
|
|
3708
3881
|
);
|
|
3709
3882
|
}
|
|
3710
3883
|
|
|
3711
|
-
// Context-aware variant that preserves the priority
|
|
3884
|
+
// Context-aware variant that preserves the priority and context key
|
|
3885
|
+
// mappings on deregistration so frozen dispatch snapshots remain valid
|
|
3886
|
+
// for any in-flight emission. Trade-off: empty HandlerActionCache
|
|
3887
|
+
// entries (and their enclosing per-priority Dictionary) are not
|
|
3888
|
+
// reclaimed until either (a) a future registration at the same
|
|
3889
|
+
// (context, priority) pair reuses the cache, or (b) the owning
|
|
3890
|
+
// MessageHandler is destroyed. For typical Unity gameplay (a small
|
|
3891
|
+
// fixed set of priorities and a bounded set of long-lived target /
|
|
3892
|
+
// source InstanceIds) the residual footprint is on the order of
|
|
3893
|
+
// hundreds of bytes per MessageHandler. Code that interacts with
|
|
3894
|
+
// many transient InstanceIds (e.g. a global service that registers
|
|
3895
|
+
// handlers per ephemeral GameObject) should prefer recycling
|
|
3896
|
+
// MessageHandlers or routing through AddSourcedBroadcastWithoutSourceHandler /
|
|
3897
|
+
// AddTargetedWithoutTargetingHandler to avoid the per-(context,priority)
|
|
3898
|
+
// outer-dictionary growth.
|
|
3899
|
+
// `flatInvoker` carries the pre-resolved flat-dispatch invoker for
|
|
3900
|
+
// default-shape registrations the bus-side flat snapshot consumes
|
|
3901
|
+
// (FastHandler adapter wrapping the augmented handler); see
|
|
3902
|
+
// HandlerActionCache.Entry.flatInvoker.
|
|
3903
|
+
private Action AddHandlerPreservingPriorityKey<TU>(
|
|
3904
|
+
InstanceId context,
|
|
3905
|
+
Dictionary<InstanceId, Dictionary<int, IHandlerActionCache>> handlersByContext,
|
|
3906
|
+
TU originalHandler,
|
|
3907
|
+
TU augmentedHandler,
|
|
3908
|
+
Action deregistration,
|
|
3909
|
+
int priority,
|
|
3910
|
+
IMessageBus messageBus,
|
|
3911
|
+
object flatInvoker = null
|
|
3912
|
+
)
|
|
3913
|
+
{
|
|
3914
|
+
if (
|
|
3915
|
+
!handlersByContext.TryGetValue(
|
|
3916
|
+
context,
|
|
3917
|
+
out Dictionary<int, IHandlerActionCache> sortedHandlers
|
|
3918
|
+
)
|
|
3919
|
+
)
|
|
3920
|
+
{
|
|
3921
|
+
sortedHandlers = DxPools.TypedHandlerPriorityDicts.Rent();
|
|
3922
|
+
handlersByContext[context] = sortedHandlers;
|
|
3923
|
+
}
|
|
3924
|
+
|
|
3925
|
+
if (
|
|
3926
|
+
!sortedHandlers.TryGetValue(priority, out IHandlerActionCache erasedCache)
|
|
3927
|
+
|| erasedCache is not HandlerActionCache<TU> cache
|
|
3928
|
+
)
|
|
3929
|
+
{
|
|
3930
|
+
cache = new HandlerActionCache<TU>();
|
|
3931
|
+
sortedHandlers[priority] = cache;
|
|
3932
|
+
}
|
|
3933
|
+
|
|
3934
|
+
if (
|
|
3935
|
+
!cache.entries.TryGetValue(
|
|
3936
|
+
originalHandler,
|
|
3937
|
+
out HandlerActionCache<TU>.Entry entry
|
|
3938
|
+
)
|
|
3939
|
+
)
|
|
3940
|
+
{
|
|
3941
|
+
entry = new HandlerActionCache<TU>.Entry(augmentedHandler, 0);
|
|
3942
|
+
}
|
|
3943
|
+
|
|
3944
|
+
bool firstRegistration = entry.count == 0;
|
|
3945
|
+
entry = firstRegistration
|
|
3946
|
+
? new HandlerActionCache<TU>.Entry(augmentedHandler, 1, flatInvoker)
|
|
3947
|
+
: new HandlerActionCache<TU>.Entry(
|
|
3948
|
+
entry.handler,
|
|
3949
|
+
entry.count + 1,
|
|
3950
|
+
entry.flatInvoker
|
|
3951
|
+
);
|
|
3952
|
+
|
|
3953
|
+
cache.entries[originalHandler] = entry;
|
|
3954
|
+
if (firstRegistration)
|
|
3955
|
+
{
|
|
3956
|
+
cache.insertionOrder.Add(originalHandler);
|
|
3957
|
+
}
|
|
3958
|
+
cache.version++;
|
|
3959
|
+
TypedSlot<T> slot = FindContextSlot(handlersByContext);
|
|
3960
|
+
if (slot != null)
|
|
3961
|
+
{
|
|
3962
|
+
slot.lastTouchTicks =
|
|
3963
|
+
global::DxMessaging.Core.MessageBus.MessageBus.GetCurrentTouchTick(
|
|
3964
|
+
messageBus
|
|
3965
|
+
);
|
|
3966
|
+
}
|
|
3967
|
+
if (firstRegistration && slot != null)
|
|
3968
|
+
{
|
|
3969
|
+
slot.liveCount++;
|
|
3970
|
+
}
|
|
3971
|
+
|
|
3972
|
+
Dictionary<
|
|
3973
|
+
InstanceId,
|
|
3974
|
+
Dictionary<int, IHandlerActionCache>
|
|
3975
|
+
> localHandlersByContext = handlersByContext;
|
|
3976
|
+
TypedSlot<T> localSlot = slot;
|
|
3977
|
+
long localSlotVersion = slot?.version ?? 0;
|
|
3978
|
+
long localResetGeneration =
|
|
3979
|
+
global::DxMessaging.Core.MessageBus.MessageBus.GetResetGeneration(messageBus);
|
|
3980
|
+
|
|
3981
|
+
return () =>
|
|
3982
|
+
{
|
|
3983
|
+
if (
|
|
3984
|
+
!global::DxMessaging.Core.MessageBus.MessageBus.IsResetGenerationCurrent(
|
|
3985
|
+
messageBus,
|
|
3986
|
+
localResetGeneration
|
|
3987
|
+
)
|
|
3988
|
+
)
|
|
3989
|
+
{
|
|
3990
|
+
return;
|
|
3991
|
+
}
|
|
3992
|
+
|
|
3993
|
+
if (localSlot != null && localSlot.version != localSlotVersion)
|
|
3994
|
+
{
|
|
3995
|
+
return;
|
|
3996
|
+
}
|
|
3997
|
+
|
|
3998
|
+
if (!localHandlersByContext.TryGetValue(context, out sortedHandlers))
|
|
3999
|
+
{
|
|
4000
|
+
return;
|
|
4001
|
+
}
|
|
4002
|
+
|
|
4003
|
+
if (
|
|
4004
|
+
!sortedHandlers.TryGetValue(
|
|
4005
|
+
priority,
|
|
4006
|
+
out IHandlerActionCache localErasedCache
|
|
4007
|
+
) || localErasedCache is not HandlerActionCache<TU> localCache
|
|
4008
|
+
)
|
|
4009
|
+
{
|
|
4010
|
+
return;
|
|
4011
|
+
}
|
|
4012
|
+
|
|
4013
|
+
if (
|
|
4014
|
+
!localCache.entries.TryGetValue(
|
|
4015
|
+
originalHandler,
|
|
4016
|
+
out HandlerActionCache<TU>.Entry localEntry
|
|
4017
|
+
)
|
|
4018
|
+
)
|
|
4019
|
+
{
|
|
4020
|
+
return;
|
|
4021
|
+
}
|
|
4022
|
+
|
|
4023
|
+
localCache.version++;
|
|
4024
|
+
|
|
4025
|
+
deregistration?.Invoke();
|
|
4026
|
+
if (localSlot != null)
|
|
4027
|
+
{
|
|
4028
|
+
localSlot.lastTouchTicks =
|
|
4029
|
+
global::DxMessaging.Core.MessageBus.MessageBus.GetCurrentTouchTick(
|
|
4030
|
+
messageBus
|
|
4031
|
+
);
|
|
4032
|
+
}
|
|
4033
|
+
|
|
4034
|
+
if (localEntry.count <= 1)
|
|
4035
|
+
{
|
|
4036
|
+
_ = localCache.entries.Remove(originalHandler);
|
|
4037
|
+
// List.Remove is O(n) over the same-priority bucket.
|
|
4038
|
+
// Accepted tradeoff (here and at every sibling
|
|
4039
|
+
// deregistration site): buckets are small in practice,
|
|
4040
|
+
// removal is a cold churn path, and the list keeps
|
|
4041
|
+
// steady-state dispatch allocation-free while
|
|
4042
|
+
// preserving first-registration order, unlike
|
|
4043
|
+
// Dictionary enumeration whose freed slots are reused
|
|
4044
|
+
// LIFO.
|
|
4045
|
+
_ = localCache.insertionOrder.Remove(originalHandler);
|
|
4046
|
+
localCache.version++;
|
|
4047
|
+
if (localSlot != null)
|
|
4048
|
+
{
|
|
4049
|
+
localSlot.liveCount--;
|
|
4050
|
+
}
|
|
4051
|
+
// Deliberately keep the priority and context mappings to preserve
|
|
4052
|
+
// frozen snapshots for the current emission.
|
|
4053
|
+
return;
|
|
4054
|
+
}
|
|
4055
|
+
|
|
4056
|
+
localEntry = new HandlerActionCache<TU>.Entry(
|
|
4057
|
+
localEntry.handler,
|
|
4058
|
+
localEntry.count - 1,
|
|
4059
|
+
localEntry.flatInvoker
|
|
4060
|
+
);
|
|
4061
|
+
|
|
4062
|
+
localCache.entries[originalHandler] = localEntry;
|
|
4063
|
+
};
|
|
4064
|
+
}
|
|
4065
|
+
|
|
3712
4066
|
private static Action AddHandlerPreservingPriorityKey<TU>(
|
|
3713
4067
|
InstanceId context,
|
|
3714
4068
|
ref Dictionary<
|
|
@@ -3719,7 +4073,7 @@ namespace DxMessaging.Core
|
|
|
3719
4073
|
TU augmentedHandler,
|
|
3720
4074
|
Action deregistration,
|
|
3721
4075
|
int priority,
|
|
3722
|
-
|
|
4076
|
+
IMessageBus messageBus
|
|
3723
4077
|
)
|
|
3724
4078
|
{
|
|
3725
4079
|
handlersByContext ??=
|
|
@@ -3758,6 +4112,10 @@ namespace DxMessaging.Core
|
|
|
3758
4112
|
: new HandlerActionCache<TU>.Entry(entry.handler, entry.count + 1);
|
|
3759
4113
|
|
|
3760
4114
|
cache.entries[originalHandler] = entry;
|
|
4115
|
+
if (firstRegistration)
|
|
4116
|
+
{
|
|
4117
|
+
cache.insertionOrder.Add(originalHandler);
|
|
4118
|
+
}
|
|
3761
4119
|
cache.version++;
|
|
3762
4120
|
|
|
3763
4121
|
Dictionary<
|
|
@@ -3796,6 +4154,7 @@ namespace DxMessaging.Core
|
|
|
3796
4154
|
if (localEntry.count <= 1)
|
|
3797
4155
|
{
|
|
3798
4156
|
_ = localCache.entries.Remove(originalHandler);
|
|
4157
|
+
_ = localCache.insertionOrder.Remove(originalHandler);
|
|
3799
4158
|
localCache.version++;
|
|
3800
4159
|
// Deliberately keep the priority and context mappings to preserve
|
|
3801
4160
|
// frozen snapshots for the current emission.
|
|
@@ -3807,8 +4166,43 @@ namespace DxMessaging.Core
|
|
|
3807
4166
|
localEntry.count - 1
|
|
3808
4167
|
);
|
|
3809
4168
|
|
|
3810
|
-
localCache.entries[originalHandler] = localEntry;
|
|
3811
|
-
};
|
|
4169
|
+
localCache.entries[originalHandler] = localEntry;
|
|
4170
|
+
};
|
|
4171
|
+
}
|
|
4172
|
+
|
|
4173
|
+
private static void RunFastHandlersWithContext<TMessage>(
|
|
4174
|
+
ref InstanceId context,
|
|
4175
|
+
Dictionary<int, IHandlerActionCache> fastHandlers,
|
|
4176
|
+
ref TMessage message,
|
|
4177
|
+
int priority,
|
|
4178
|
+
long emissionId
|
|
4179
|
+
)
|
|
4180
|
+
where TMessage : IMessage
|
|
4181
|
+
{
|
|
4182
|
+
RunFastHandlers(ref context, fastHandlers, ref message, priority, emissionId);
|
|
4183
|
+
}
|
|
4184
|
+
|
|
4185
|
+
private static void RunFastHandlersWithContext<TMessage>(
|
|
4186
|
+
ref InstanceId context,
|
|
4187
|
+
Dictionary<InstanceId, Dictionary<int, IHandlerActionCache>> fastHandlersByContext,
|
|
4188
|
+
ref TMessage message,
|
|
4189
|
+
int priority,
|
|
4190
|
+
long emissionId
|
|
4191
|
+
)
|
|
4192
|
+
where TMessage : IMessage
|
|
4193
|
+
{
|
|
4194
|
+
if (
|
|
4195
|
+
fastHandlersByContext is not { Count: > 0 }
|
|
4196
|
+
|| !fastHandlersByContext.TryGetValue(
|
|
4197
|
+
context,
|
|
4198
|
+
out Dictionary<int, IHandlerActionCache> cache
|
|
4199
|
+
)
|
|
4200
|
+
)
|
|
4201
|
+
{
|
|
4202
|
+
return;
|
|
4203
|
+
}
|
|
4204
|
+
|
|
4205
|
+
RunFastHandlers(cache, ref message, priority, emissionId);
|
|
3812
4206
|
}
|
|
3813
4207
|
|
|
3814
4208
|
private static void RunFastHandlersWithContext<TMessage>(
|
|
@@ -3863,6 +4257,115 @@ namespace DxMessaging.Core
|
|
|
3863
4257
|
RunFastHandlers(cache, ref message, priority, emissionId);
|
|
3864
4258
|
}
|
|
3865
4259
|
|
|
4260
|
+
private static void RunFastHandlers<TMessage>(
|
|
4261
|
+
Dictionary<int, IHandlerActionCache> fastHandlers,
|
|
4262
|
+
ref TMessage message,
|
|
4263
|
+
int priority,
|
|
4264
|
+
long emissionId
|
|
4265
|
+
)
|
|
4266
|
+
where TMessage : IMessage
|
|
4267
|
+
{
|
|
4268
|
+
if (fastHandlers is not { Count: > 0 })
|
|
4269
|
+
{
|
|
4270
|
+
return;
|
|
4271
|
+
}
|
|
4272
|
+
|
|
4273
|
+
if (
|
|
4274
|
+
!fastHandlers.TryGetValue(priority, out IHandlerActionCache erasedCache)
|
|
4275
|
+
|| erasedCache is not HandlerActionCache<FastHandler<T>> cache
|
|
4276
|
+
)
|
|
4277
|
+
{
|
|
4278
|
+
return;
|
|
4279
|
+
}
|
|
4280
|
+
|
|
4281
|
+
ref T typedMessage = ref DxUnsafe.As<TMessage, T>(ref message);
|
|
4282
|
+
List<FastHandler<T>> handlers = GetOrAddNewHandlerStack(cache, emissionId);
|
|
4283
|
+
int handlersCount = handlers.Count;
|
|
4284
|
+
switch (handlersCount)
|
|
4285
|
+
{
|
|
4286
|
+
case 1:
|
|
4287
|
+
{
|
|
4288
|
+
handlers[0](ref typedMessage);
|
|
4289
|
+
return;
|
|
4290
|
+
}
|
|
4291
|
+
case 2:
|
|
4292
|
+
{
|
|
4293
|
+
handlers[0](ref typedMessage);
|
|
4294
|
+
if (handlers.Count < 2)
|
|
4295
|
+
{
|
|
4296
|
+
return;
|
|
4297
|
+
}
|
|
4298
|
+
handlers[1](ref typedMessage);
|
|
4299
|
+
return;
|
|
4300
|
+
}
|
|
4301
|
+
case 3:
|
|
4302
|
+
{
|
|
4303
|
+
handlers[0](ref typedMessage);
|
|
4304
|
+
if (handlers.Count < 2)
|
|
4305
|
+
{
|
|
4306
|
+
return;
|
|
4307
|
+
}
|
|
4308
|
+
handlers[1](ref typedMessage);
|
|
4309
|
+
if (handlers.Count < 3)
|
|
4310
|
+
{
|
|
4311
|
+
return;
|
|
4312
|
+
}
|
|
4313
|
+
handlers[2](ref typedMessage);
|
|
4314
|
+
return;
|
|
4315
|
+
}
|
|
4316
|
+
case 4:
|
|
4317
|
+
{
|
|
4318
|
+
handlers[0](ref typedMessage);
|
|
4319
|
+
if (handlers.Count < 2)
|
|
4320
|
+
{
|
|
4321
|
+
return;
|
|
4322
|
+
}
|
|
4323
|
+
handlers[1](ref typedMessage);
|
|
4324
|
+
if (handlers.Count < 3)
|
|
4325
|
+
{
|
|
4326
|
+
return;
|
|
4327
|
+
}
|
|
4328
|
+
handlers[2](ref typedMessage);
|
|
4329
|
+
if (handlers.Count < 4)
|
|
4330
|
+
{
|
|
4331
|
+
return;
|
|
4332
|
+
}
|
|
4333
|
+
handlers[3](ref typedMessage);
|
|
4334
|
+
return;
|
|
4335
|
+
}
|
|
4336
|
+
case 5:
|
|
4337
|
+
{
|
|
4338
|
+
handlers[0](ref typedMessage);
|
|
4339
|
+
if (handlers.Count < 2)
|
|
4340
|
+
{
|
|
4341
|
+
return;
|
|
4342
|
+
}
|
|
4343
|
+
handlers[1](ref typedMessage);
|
|
4344
|
+
if (handlers.Count < 3)
|
|
4345
|
+
{
|
|
4346
|
+
return;
|
|
4347
|
+
}
|
|
4348
|
+
handlers[2](ref typedMessage);
|
|
4349
|
+
if (handlers.Count < 4)
|
|
4350
|
+
{
|
|
4351
|
+
return;
|
|
4352
|
+
}
|
|
4353
|
+
handlers[3](ref typedMessage);
|
|
4354
|
+
if (handlers.Count < 5)
|
|
4355
|
+
{
|
|
4356
|
+
return;
|
|
4357
|
+
}
|
|
4358
|
+
handlers[4](ref typedMessage);
|
|
4359
|
+
return;
|
|
4360
|
+
}
|
|
4361
|
+
}
|
|
4362
|
+
|
|
4363
|
+
for (int i = 0; i < handlersCount && i < handlers.Count; ++i)
|
|
4364
|
+
{
|
|
4365
|
+
handlers[i](ref typedMessage);
|
|
4366
|
+
}
|
|
4367
|
+
}
|
|
4368
|
+
|
|
3866
4369
|
private static void RunFastHandlers<TMessage>(
|
|
3867
4370
|
Dictionary<int, HandlerActionCache<FastHandler<T>>> fastHandlers,
|
|
3868
4371
|
ref TMessage message,
|
|
@@ -3886,7 +4389,7 @@ namespace DxMessaging.Core
|
|
|
3886
4389
|
return;
|
|
3887
4390
|
}
|
|
3888
4391
|
|
|
3889
|
-
ref T typedMessage = ref
|
|
4392
|
+
ref T typedMessage = ref DxUnsafe.As<TMessage, T>(ref message);
|
|
3890
4393
|
List<FastHandler<T>> handlers = GetOrAddNewHandlerStack(cache, emissionId);
|
|
3891
4394
|
int handlersCount = handlers.Count;
|
|
3892
4395
|
switch (handlersCount)
|
|
@@ -3899,36 +4402,76 @@ namespace DxMessaging.Core
|
|
|
3899
4402
|
case 2:
|
|
3900
4403
|
{
|
|
3901
4404
|
handlers[0](ref typedMessage);
|
|
4405
|
+
if (handlers.Count < 2)
|
|
4406
|
+
{
|
|
4407
|
+
return;
|
|
4408
|
+
}
|
|
3902
4409
|
handlers[1](ref typedMessage);
|
|
3903
4410
|
return;
|
|
3904
4411
|
}
|
|
3905
4412
|
case 3:
|
|
3906
4413
|
{
|
|
3907
4414
|
handlers[0](ref typedMessage);
|
|
4415
|
+
if (handlers.Count < 2)
|
|
4416
|
+
{
|
|
4417
|
+
return;
|
|
4418
|
+
}
|
|
3908
4419
|
handlers[1](ref typedMessage);
|
|
4420
|
+
if (handlers.Count < 3)
|
|
4421
|
+
{
|
|
4422
|
+
return;
|
|
4423
|
+
}
|
|
3909
4424
|
handlers[2](ref typedMessage);
|
|
3910
4425
|
return;
|
|
3911
4426
|
}
|
|
3912
4427
|
case 4:
|
|
3913
4428
|
{
|
|
3914
4429
|
handlers[0](ref typedMessage);
|
|
4430
|
+
if (handlers.Count < 2)
|
|
4431
|
+
{
|
|
4432
|
+
return;
|
|
4433
|
+
}
|
|
3915
4434
|
handlers[1](ref typedMessage);
|
|
4435
|
+
if (handlers.Count < 3)
|
|
4436
|
+
{
|
|
4437
|
+
return;
|
|
4438
|
+
}
|
|
3916
4439
|
handlers[2](ref typedMessage);
|
|
4440
|
+
if (handlers.Count < 4)
|
|
4441
|
+
{
|
|
4442
|
+
return;
|
|
4443
|
+
}
|
|
3917
4444
|
handlers[3](ref typedMessage);
|
|
3918
4445
|
return;
|
|
3919
4446
|
}
|
|
3920
4447
|
case 5:
|
|
3921
4448
|
{
|
|
3922
4449
|
handlers[0](ref typedMessage);
|
|
4450
|
+
if (handlers.Count < 2)
|
|
4451
|
+
{
|
|
4452
|
+
return;
|
|
4453
|
+
}
|
|
3923
4454
|
handlers[1](ref typedMessage);
|
|
4455
|
+
if (handlers.Count < 3)
|
|
4456
|
+
{
|
|
4457
|
+
return;
|
|
4458
|
+
}
|
|
3924
4459
|
handlers[2](ref typedMessage);
|
|
4460
|
+
if (handlers.Count < 4)
|
|
4461
|
+
{
|
|
4462
|
+
return;
|
|
4463
|
+
}
|
|
3925
4464
|
handlers[3](ref typedMessage);
|
|
4465
|
+
if (handlers.Count < 5)
|
|
4466
|
+
{
|
|
4467
|
+
return;
|
|
4468
|
+
}
|
|
3926
4469
|
handlers[4](ref typedMessage);
|
|
3927
4470
|
return;
|
|
3928
4471
|
}
|
|
3929
4472
|
}
|
|
3930
4473
|
|
|
3931
|
-
for (int i = 0; i < handlersCount; ++i)
|
|
4474
|
+
for (int i = 0; i < handlersCount && i < handlers.Count; ++i)
|
|
3932
4475
|
{
|
|
3933
4476
|
handlers[i](ref typedMessage);
|
|
3934
4477
|
}
|
|
@@ -3942,14 +4485,33 @@ namespace DxMessaging.Core
|
|
|
3942
4485
|
where TMessage : IMessage
|
|
3943
4486
|
where TU : IMessage
|
|
3944
4487
|
{
|
|
3945
|
-
|
|
4488
|
+
// Snapshot semantics: do not bail on the live entries dictionary
|
|
4489
|
+
// count. A mid-emit removal can drain entries while the pinned
|
|
4490
|
+
// emission snapshot in cache.cache still holds the handlers we
|
|
4491
|
+
// must invoke. Read the snapshot first and bail only if the
|
|
4492
|
+
// snapshot itself is empty.
|
|
4493
|
+
//
|
|
4494
|
+
// Perf note: GetOrAddNewHandlerStack is now invoked on every
|
|
4495
|
+
// call (including for empty caches that the previous fast-path
|
|
4496
|
+
// would have skipped). The cost is one dictionary
|
|
4497
|
+
// emission-id/version compare and -- only when the per-emission
|
|
4498
|
+
// snapshot has not been pinned yet -- a single pass over
|
|
4499
|
+
// cache.entries to materialise an empty list. The win is
|
|
4500
|
+
// correctness across cross-handler mid-emit removals where the
|
|
4501
|
+
// pinned snapshot in cache.cache still holds handlers the live
|
|
4502
|
+
// entries dictionary no longer reaches.
|
|
4503
|
+
if (cache == null)
|
|
3946
4504
|
{
|
|
3947
4505
|
return;
|
|
3948
4506
|
}
|
|
3949
4507
|
|
|
3950
|
-
ref TU typedMessage = ref
|
|
4508
|
+
ref TU typedMessage = ref DxUnsafe.As<TMessage, TU>(ref message);
|
|
3951
4509
|
List<FastHandler<TU>> handlers = GetOrAddNewHandlerStack(cache, emissionId);
|
|
3952
4510
|
int handlersCount = handlers.Count;
|
|
4511
|
+
if (handlersCount == 0)
|
|
4512
|
+
{
|
|
4513
|
+
return;
|
|
4514
|
+
}
|
|
3953
4515
|
switch (handlersCount)
|
|
3954
4516
|
{
|
|
3955
4517
|
case 1:
|
|
@@ -3960,56 +4522,270 @@ namespace DxMessaging.Core
|
|
|
3960
4522
|
case 2:
|
|
3961
4523
|
{
|
|
3962
4524
|
handlers[0](ref typedMessage);
|
|
4525
|
+
if (handlers.Count < 2)
|
|
4526
|
+
{
|
|
4527
|
+
return;
|
|
4528
|
+
}
|
|
3963
4529
|
handlers[1](ref typedMessage);
|
|
3964
4530
|
return;
|
|
3965
4531
|
}
|
|
3966
4532
|
case 3:
|
|
3967
4533
|
{
|
|
3968
4534
|
handlers[0](ref typedMessage);
|
|
4535
|
+
if (handlers.Count < 2)
|
|
4536
|
+
{
|
|
4537
|
+
return;
|
|
4538
|
+
}
|
|
3969
4539
|
handlers[1](ref typedMessage);
|
|
4540
|
+
if (handlers.Count < 3)
|
|
4541
|
+
{
|
|
4542
|
+
return;
|
|
4543
|
+
}
|
|
3970
4544
|
handlers[2](ref typedMessage);
|
|
3971
4545
|
return;
|
|
3972
4546
|
}
|
|
3973
4547
|
case 4:
|
|
3974
4548
|
{
|
|
3975
4549
|
handlers[0](ref typedMessage);
|
|
4550
|
+
if (handlers.Count < 2)
|
|
4551
|
+
{
|
|
4552
|
+
return;
|
|
4553
|
+
}
|
|
3976
4554
|
handlers[1](ref typedMessage);
|
|
4555
|
+
if (handlers.Count < 3)
|
|
4556
|
+
{
|
|
4557
|
+
return;
|
|
4558
|
+
}
|
|
3977
4559
|
handlers[2](ref typedMessage);
|
|
4560
|
+
if (handlers.Count < 4)
|
|
4561
|
+
{
|
|
4562
|
+
return;
|
|
4563
|
+
}
|
|
3978
4564
|
handlers[3](ref typedMessage);
|
|
3979
4565
|
return;
|
|
3980
4566
|
}
|
|
3981
4567
|
case 5:
|
|
3982
4568
|
{
|
|
3983
4569
|
handlers[0](ref typedMessage);
|
|
4570
|
+
if (handlers.Count < 2)
|
|
4571
|
+
{
|
|
4572
|
+
return;
|
|
4573
|
+
}
|
|
3984
4574
|
handlers[1](ref typedMessage);
|
|
4575
|
+
if (handlers.Count < 3)
|
|
4576
|
+
{
|
|
4577
|
+
return;
|
|
4578
|
+
}
|
|
3985
4579
|
handlers[2](ref typedMessage);
|
|
4580
|
+
if (handlers.Count < 4)
|
|
4581
|
+
{
|
|
4582
|
+
return;
|
|
4583
|
+
}
|
|
3986
4584
|
handlers[3](ref typedMessage);
|
|
4585
|
+
if (handlers.Count < 5)
|
|
4586
|
+
{
|
|
4587
|
+
return;
|
|
4588
|
+
}
|
|
3987
4589
|
handlers[4](ref typedMessage);
|
|
3988
4590
|
return;
|
|
3989
4591
|
}
|
|
3990
4592
|
}
|
|
3991
4593
|
|
|
3992
|
-
for (int i = 0; i < handlersCount; ++i)
|
|
4594
|
+
for (int i = 0; i < handlersCount && i < handlers.Count; ++i)
|
|
4595
|
+
{
|
|
4596
|
+
handlers[i](ref typedMessage);
|
|
4597
|
+
}
|
|
4598
|
+
}
|
|
4599
|
+
|
|
4600
|
+
private static void RunFastHandlers<TMessage, TU>(
|
|
4601
|
+
ref InstanceId context,
|
|
4602
|
+
HandlerActionCache<FastHandlerWithContext<TU>> cache,
|
|
4603
|
+
ref TMessage message,
|
|
4604
|
+
long emissionId
|
|
4605
|
+
)
|
|
4606
|
+
where TMessage : IMessage
|
|
4607
|
+
where TU : IMessage
|
|
4608
|
+
{
|
|
4609
|
+
// Snapshot semantics: see comment on the FastHandler<TU> overload.
|
|
4610
|
+
// The pinned emission snapshot may still hold handlers even when
|
|
4611
|
+
// the live entries dictionary has been drained mid-emit.
|
|
4612
|
+
if (cache == null)
|
|
4613
|
+
{
|
|
4614
|
+
return;
|
|
4615
|
+
}
|
|
4616
|
+
|
|
4617
|
+
ref TU typedMessage = ref DxUnsafe.As<TMessage, TU>(ref message);
|
|
4618
|
+
List<FastHandlerWithContext<TU>> handlers = GetOrAddNewHandlerStack(
|
|
4619
|
+
cache,
|
|
4620
|
+
emissionId
|
|
4621
|
+
);
|
|
4622
|
+
int handlersCount = handlers.Count;
|
|
4623
|
+
if (handlersCount == 0)
|
|
4624
|
+
{
|
|
4625
|
+
return;
|
|
4626
|
+
}
|
|
4627
|
+
switch (handlersCount)
|
|
4628
|
+
{
|
|
4629
|
+
case 1:
|
|
4630
|
+
{
|
|
4631
|
+
handlers[0](ref context, ref typedMessage);
|
|
4632
|
+
return;
|
|
4633
|
+
}
|
|
4634
|
+
case 2:
|
|
4635
|
+
{
|
|
4636
|
+
handlers[0](ref context, ref typedMessage);
|
|
4637
|
+
if (handlers.Count < 2)
|
|
4638
|
+
{
|
|
4639
|
+
return;
|
|
4640
|
+
}
|
|
4641
|
+
handlers[1](ref context, ref typedMessage);
|
|
4642
|
+
return;
|
|
4643
|
+
}
|
|
4644
|
+
case 3:
|
|
4645
|
+
{
|
|
4646
|
+
handlers[0](ref context, ref typedMessage);
|
|
4647
|
+
if (handlers.Count < 2)
|
|
4648
|
+
{
|
|
4649
|
+
return;
|
|
4650
|
+
}
|
|
4651
|
+
handlers[1](ref context, ref typedMessage);
|
|
4652
|
+
if (handlers.Count < 3)
|
|
4653
|
+
{
|
|
4654
|
+
return;
|
|
4655
|
+
}
|
|
4656
|
+
handlers[2](ref context, ref typedMessage);
|
|
4657
|
+
return;
|
|
4658
|
+
}
|
|
4659
|
+
case 4:
|
|
4660
|
+
{
|
|
4661
|
+
handlers[0](ref context, ref typedMessage);
|
|
4662
|
+
if (handlers.Count < 2)
|
|
4663
|
+
{
|
|
4664
|
+
return;
|
|
4665
|
+
}
|
|
4666
|
+
handlers[1](ref context, ref typedMessage);
|
|
4667
|
+
if (handlers.Count < 3)
|
|
4668
|
+
{
|
|
4669
|
+
return;
|
|
4670
|
+
}
|
|
4671
|
+
handlers[2](ref context, ref typedMessage);
|
|
4672
|
+
if (handlers.Count < 4)
|
|
4673
|
+
{
|
|
4674
|
+
return;
|
|
4675
|
+
}
|
|
4676
|
+
handlers[3](ref context, ref typedMessage);
|
|
4677
|
+
return;
|
|
4678
|
+
}
|
|
4679
|
+
case 5:
|
|
4680
|
+
{
|
|
4681
|
+
handlers[0](ref context, ref typedMessage);
|
|
4682
|
+
if (handlers.Count < 2)
|
|
4683
|
+
{
|
|
4684
|
+
return;
|
|
4685
|
+
}
|
|
4686
|
+
handlers[1](ref context, ref typedMessage);
|
|
4687
|
+
if (handlers.Count < 3)
|
|
4688
|
+
{
|
|
4689
|
+
return;
|
|
4690
|
+
}
|
|
4691
|
+
handlers[2](ref context, ref typedMessage);
|
|
4692
|
+
if (handlers.Count < 4)
|
|
4693
|
+
{
|
|
4694
|
+
return;
|
|
4695
|
+
}
|
|
4696
|
+
handlers[3](ref context, ref typedMessage);
|
|
4697
|
+
if (handlers.Count < 5)
|
|
4698
|
+
{
|
|
4699
|
+
return;
|
|
4700
|
+
}
|
|
4701
|
+
handlers[4](ref context, ref typedMessage);
|
|
4702
|
+
return;
|
|
4703
|
+
}
|
|
4704
|
+
}
|
|
4705
|
+
|
|
4706
|
+
for (int i = 0; i < handlersCount && i < handlers.Count; ++i)
|
|
4707
|
+
{
|
|
4708
|
+
handlers[i](ref context, ref typedMessage);
|
|
4709
|
+
}
|
|
4710
|
+
}
|
|
4711
|
+
|
|
4712
|
+
private static void RunFastHandlers<TMessage>(
|
|
4713
|
+
ref InstanceId context,
|
|
4714
|
+
Dictionary<int, IHandlerActionCache> fastHandlers,
|
|
4715
|
+
ref TMessage message,
|
|
4716
|
+
int priority,
|
|
4717
|
+
long emissionId
|
|
4718
|
+
)
|
|
4719
|
+
where TMessage : IMessage
|
|
4720
|
+
{
|
|
4721
|
+
if (fastHandlers is not { Count: > 0 })
|
|
4722
|
+
{
|
|
4723
|
+
return;
|
|
4724
|
+
}
|
|
4725
|
+
|
|
4726
|
+
if (
|
|
4727
|
+
!fastHandlers.TryGetValue(priority, out IHandlerActionCache erasedCache)
|
|
4728
|
+
|| erasedCache is not HandlerActionCache<FastHandlerWithContext<T>> cache
|
|
4729
|
+
)
|
|
4730
|
+
{
|
|
4731
|
+
return;
|
|
4732
|
+
}
|
|
4733
|
+
|
|
4734
|
+
RunFastHandlers(ref context, cache, ref message, emissionId);
|
|
4735
|
+
}
|
|
4736
|
+
|
|
4737
|
+
private static void RunFastHandlers<TMessage, TU>(
|
|
4738
|
+
ref InstanceId context,
|
|
4739
|
+
Dictionary<int, IHandlerActionCache> fastHandlers,
|
|
4740
|
+
ref TMessage message,
|
|
4741
|
+
int priority,
|
|
4742
|
+
long emissionId
|
|
4743
|
+
)
|
|
4744
|
+
where TMessage : IMessage
|
|
4745
|
+
where TU : IMessage
|
|
4746
|
+
{
|
|
4747
|
+
if (fastHandlers is not { Count: > 0 })
|
|
4748
|
+
{
|
|
4749
|
+
return;
|
|
4750
|
+
}
|
|
4751
|
+
|
|
4752
|
+
if (
|
|
4753
|
+
!fastHandlers.TryGetValue(priority, out IHandlerActionCache erasedCache)
|
|
4754
|
+
|| erasedCache is not HandlerActionCache<FastHandlerWithContext<TU>> cache
|
|
4755
|
+
)
|
|
3993
4756
|
{
|
|
3994
|
-
|
|
4757
|
+
return;
|
|
3995
4758
|
}
|
|
4759
|
+
|
|
4760
|
+
RunFastHandlers(ref context, cache, ref message, emissionId);
|
|
3996
4761
|
}
|
|
3997
4762
|
|
|
3998
4763
|
private static void RunFastHandlers<TMessage, TU>(
|
|
3999
4764
|
ref InstanceId context,
|
|
4000
|
-
HandlerActionCache<FastHandlerWithContext<TU
|
|
4765
|
+
Dictionary<int, HandlerActionCache<FastHandlerWithContext<TU>>> fastHandlers,
|
|
4001
4766
|
ref TMessage message,
|
|
4767
|
+
int priority,
|
|
4002
4768
|
long emissionId
|
|
4003
4769
|
)
|
|
4004
4770
|
where TMessage : IMessage
|
|
4005
4771
|
where TU : IMessage
|
|
4006
4772
|
{
|
|
4007
|
-
if (
|
|
4773
|
+
if (fastHandlers is not { Count: > 0 })
|
|
4774
|
+
{
|
|
4775
|
+
return;
|
|
4776
|
+
}
|
|
4777
|
+
|
|
4778
|
+
if (
|
|
4779
|
+
!fastHandlers.TryGetValue(
|
|
4780
|
+
priority,
|
|
4781
|
+
out HandlerActionCache<FastHandlerWithContext<TU>> cache
|
|
4782
|
+
)
|
|
4783
|
+
)
|
|
4008
4784
|
{
|
|
4009
4785
|
return;
|
|
4010
4786
|
}
|
|
4011
4787
|
|
|
4012
|
-
ref TU typedMessage = ref
|
|
4788
|
+
ref TU typedMessage = ref DxUnsafe.As<TMessage, TU>(ref message);
|
|
4013
4789
|
List<FastHandlerWithContext<TU>> handlers = GetOrAddNewHandlerStack(
|
|
4014
4790
|
cache,
|
|
4015
4791
|
emissionId
|
|
@@ -4025,206 +4801,455 @@ namespace DxMessaging.Core
|
|
|
4025
4801
|
case 2:
|
|
4026
4802
|
{
|
|
4027
4803
|
handlers[0](ref context, ref typedMessage);
|
|
4804
|
+
if (handlers.Count < 2)
|
|
4805
|
+
{
|
|
4806
|
+
return;
|
|
4807
|
+
}
|
|
4028
4808
|
handlers[1](ref context, ref typedMessage);
|
|
4029
4809
|
return;
|
|
4030
4810
|
}
|
|
4031
4811
|
case 3:
|
|
4032
4812
|
{
|
|
4033
4813
|
handlers[0](ref context, ref typedMessage);
|
|
4814
|
+
if (handlers.Count < 2)
|
|
4815
|
+
{
|
|
4816
|
+
return;
|
|
4817
|
+
}
|
|
4034
4818
|
handlers[1](ref context, ref typedMessage);
|
|
4819
|
+
if (handlers.Count < 3)
|
|
4820
|
+
{
|
|
4821
|
+
return;
|
|
4822
|
+
}
|
|
4035
4823
|
handlers[2](ref context, ref typedMessage);
|
|
4036
4824
|
return;
|
|
4037
4825
|
}
|
|
4038
4826
|
case 4:
|
|
4039
4827
|
{
|
|
4040
4828
|
handlers[0](ref context, ref typedMessage);
|
|
4829
|
+
if (handlers.Count < 2)
|
|
4830
|
+
{
|
|
4831
|
+
return;
|
|
4832
|
+
}
|
|
4041
4833
|
handlers[1](ref context, ref typedMessage);
|
|
4834
|
+
if (handlers.Count < 3)
|
|
4835
|
+
{
|
|
4836
|
+
return;
|
|
4837
|
+
}
|
|
4042
4838
|
handlers[2](ref context, ref typedMessage);
|
|
4839
|
+
if (handlers.Count < 4)
|
|
4840
|
+
{
|
|
4841
|
+
return;
|
|
4842
|
+
}
|
|
4043
4843
|
handlers[3](ref context, ref typedMessage);
|
|
4044
4844
|
return;
|
|
4045
4845
|
}
|
|
4046
4846
|
case 5:
|
|
4047
4847
|
{
|
|
4048
4848
|
handlers[0](ref context, ref typedMessage);
|
|
4849
|
+
if (handlers.Count < 2)
|
|
4850
|
+
{
|
|
4851
|
+
return;
|
|
4852
|
+
}
|
|
4049
4853
|
handlers[1](ref context, ref typedMessage);
|
|
4854
|
+
if (handlers.Count < 3)
|
|
4855
|
+
{
|
|
4856
|
+
return;
|
|
4857
|
+
}
|
|
4050
4858
|
handlers[2](ref context, ref typedMessage);
|
|
4859
|
+
if (handlers.Count < 4)
|
|
4860
|
+
{
|
|
4861
|
+
return;
|
|
4862
|
+
}
|
|
4051
4863
|
handlers[3](ref context, ref typedMessage);
|
|
4864
|
+
if (handlers.Count < 5)
|
|
4865
|
+
{
|
|
4866
|
+
return;
|
|
4867
|
+
}
|
|
4052
4868
|
handlers[4](ref context, ref typedMessage);
|
|
4053
4869
|
return;
|
|
4054
4870
|
}
|
|
4055
4871
|
}
|
|
4056
4872
|
|
|
4057
|
-
for (int i = 0; i < handlersCount; ++i)
|
|
4873
|
+
for (int i = 0; i < handlersCount && i < handlers.Count; ++i)
|
|
4058
4874
|
{
|
|
4059
4875
|
handlers[i](ref context, ref typedMessage);
|
|
4060
4876
|
}
|
|
4061
4877
|
}
|
|
4062
4878
|
|
|
4063
|
-
private static void
|
|
4879
|
+
private static void RunHandlersWithContext<TMessage>(
|
|
4064
4880
|
ref InstanceId context,
|
|
4065
|
-
Dictionary<
|
|
4881
|
+
Dictionary<InstanceId, Dictionary<int, IHandlerActionCache>> handlersByContext,
|
|
4066
4882
|
ref TMessage message,
|
|
4067
4883
|
int priority,
|
|
4068
4884
|
long emissionId
|
|
4069
4885
|
)
|
|
4070
4886
|
where TMessage : IMessage
|
|
4071
|
-
where TU : IMessage
|
|
4072
4887
|
{
|
|
4073
|
-
if (
|
|
4888
|
+
if (
|
|
4889
|
+
handlersByContext is not { Count: > 0 }
|
|
4890
|
+
|| !handlersByContext.TryGetValue(
|
|
4891
|
+
context,
|
|
4892
|
+
out Dictionary<int, IHandlerActionCache> cache
|
|
4893
|
+
)
|
|
4894
|
+
)
|
|
4074
4895
|
{
|
|
4075
4896
|
return;
|
|
4076
4897
|
}
|
|
4077
4898
|
|
|
4899
|
+
RunHandlers(cache, ref message, priority, emissionId);
|
|
4900
|
+
}
|
|
4901
|
+
|
|
4902
|
+
private static void RunHandlersWithContext<TMessage>(
|
|
4903
|
+
ref InstanceId context,
|
|
4904
|
+
Dictionary<
|
|
4905
|
+
InstanceId,
|
|
4906
|
+
Dictionary<int, HandlerActionCache<Action<T>>>
|
|
4907
|
+
> handlersByContext,
|
|
4908
|
+
ref TMessage message,
|
|
4909
|
+
int priority,
|
|
4910
|
+
long emissionId
|
|
4911
|
+
)
|
|
4912
|
+
where TMessage : IMessage
|
|
4913
|
+
{
|
|
4078
4914
|
if (
|
|
4079
|
-
|
|
4080
|
-
|
|
4081
|
-
|
|
4915
|
+
handlersByContext is not { Count: > 0 }
|
|
4916
|
+
|| !handlersByContext.TryGetValue(
|
|
4917
|
+
context,
|
|
4918
|
+
out Dictionary<int, HandlerActionCache<Action<T>>> cache
|
|
4082
4919
|
)
|
|
4083
4920
|
)
|
|
4084
4921
|
{
|
|
4085
4922
|
return;
|
|
4086
4923
|
}
|
|
4087
4924
|
|
|
4088
|
-
|
|
4089
|
-
|
|
4090
|
-
|
|
4091
|
-
|
|
4092
|
-
|
|
4925
|
+
RunHandlers(cache, ref message, priority, emissionId);
|
|
4926
|
+
}
|
|
4927
|
+
|
|
4928
|
+
private static void RunHandlers<TMessage>(
|
|
4929
|
+
Dictionary<int, IHandlerActionCache> sortedHandlers,
|
|
4930
|
+
ref TMessage message,
|
|
4931
|
+
int priority,
|
|
4932
|
+
long emissionId
|
|
4933
|
+
)
|
|
4934
|
+
where TMessage : IMessage
|
|
4935
|
+
{
|
|
4936
|
+
if (sortedHandlers is not { Count: > 0 })
|
|
4937
|
+
{
|
|
4938
|
+
return;
|
|
4939
|
+
}
|
|
4940
|
+
|
|
4941
|
+
if (
|
|
4942
|
+
!sortedHandlers.TryGetValue(priority, out IHandlerActionCache erasedCache)
|
|
4943
|
+
|| erasedCache is not HandlerActionCache<Action<T>> cache
|
|
4944
|
+
)
|
|
4945
|
+
{
|
|
4946
|
+
return;
|
|
4947
|
+
}
|
|
4948
|
+
|
|
4949
|
+
List<Action<T>> handlers = GetOrAddNewHandlerStack(cache, emissionId);
|
|
4950
|
+
ref T typedMessage = ref DxUnsafe.As<TMessage, T>(ref message);
|
|
4093
4951
|
int handlersCount = handlers.Count;
|
|
4094
4952
|
switch (handlersCount)
|
|
4095
4953
|
{
|
|
4096
4954
|
case 1:
|
|
4097
4955
|
{
|
|
4098
|
-
handlers[0](
|
|
4956
|
+
handlers[0](typedMessage);
|
|
4099
4957
|
return;
|
|
4100
4958
|
}
|
|
4101
4959
|
case 2:
|
|
4102
4960
|
{
|
|
4103
|
-
handlers[0](
|
|
4104
|
-
handlers
|
|
4961
|
+
handlers[0](typedMessage);
|
|
4962
|
+
if (handlers.Count < 2)
|
|
4963
|
+
{
|
|
4964
|
+
return;
|
|
4965
|
+
}
|
|
4966
|
+
handlers[1](typedMessage);
|
|
4105
4967
|
return;
|
|
4106
4968
|
}
|
|
4107
4969
|
case 3:
|
|
4108
4970
|
{
|
|
4109
|
-
handlers[0](
|
|
4110
|
-
handlers
|
|
4111
|
-
|
|
4971
|
+
handlers[0](typedMessage);
|
|
4972
|
+
if (handlers.Count < 2)
|
|
4973
|
+
{
|
|
4974
|
+
return;
|
|
4975
|
+
}
|
|
4976
|
+
handlers[1](typedMessage);
|
|
4977
|
+
if (handlers.Count < 3)
|
|
4978
|
+
{
|
|
4979
|
+
return;
|
|
4980
|
+
}
|
|
4981
|
+
handlers[2](typedMessage);
|
|
4112
4982
|
return;
|
|
4113
4983
|
}
|
|
4114
4984
|
case 4:
|
|
4115
4985
|
{
|
|
4116
|
-
handlers[0](
|
|
4117
|
-
handlers
|
|
4118
|
-
|
|
4119
|
-
|
|
4986
|
+
handlers[0](typedMessage);
|
|
4987
|
+
if (handlers.Count < 2)
|
|
4988
|
+
{
|
|
4989
|
+
return;
|
|
4990
|
+
}
|
|
4991
|
+
handlers[1](typedMessage);
|
|
4992
|
+
if (handlers.Count < 3)
|
|
4993
|
+
{
|
|
4994
|
+
return;
|
|
4995
|
+
}
|
|
4996
|
+
handlers[2](typedMessage);
|
|
4997
|
+
if (handlers.Count < 4)
|
|
4998
|
+
{
|
|
4999
|
+
return;
|
|
5000
|
+
}
|
|
5001
|
+
handlers[3](typedMessage);
|
|
4120
5002
|
return;
|
|
4121
5003
|
}
|
|
4122
5004
|
case 5:
|
|
4123
5005
|
{
|
|
4124
|
-
handlers[0](
|
|
4125
|
-
handlers
|
|
4126
|
-
|
|
4127
|
-
|
|
4128
|
-
|
|
5006
|
+
handlers[0](typedMessage);
|
|
5007
|
+
if (handlers.Count < 2)
|
|
5008
|
+
{
|
|
5009
|
+
return;
|
|
5010
|
+
}
|
|
5011
|
+
handlers[1](typedMessage);
|
|
5012
|
+
if (handlers.Count < 3)
|
|
5013
|
+
{
|
|
5014
|
+
return;
|
|
5015
|
+
}
|
|
5016
|
+
handlers[2](typedMessage);
|
|
5017
|
+
if (handlers.Count < 4)
|
|
5018
|
+
{
|
|
5019
|
+
return;
|
|
5020
|
+
}
|
|
5021
|
+
handlers[3](typedMessage);
|
|
5022
|
+
if (handlers.Count < 5)
|
|
5023
|
+
{
|
|
5024
|
+
return;
|
|
5025
|
+
}
|
|
5026
|
+
handlers[4](typedMessage);
|
|
4129
5027
|
return;
|
|
4130
5028
|
}
|
|
4131
5029
|
}
|
|
4132
5030
|
|
|
4133
|
-
for (int i = 0; i < handlersCount; ++i)
|
|
5031
|
+
for (int i = 0; i < handlersCount && i < handlers.Count; ++i)
|
|
4134
5032
|
{
|
|
4135
|
-
handlers[i](
|
|
5033
|
+
handlers[i](typedMessage);
|
|
4136
5034
|
}
|
|
4137
5035
|
}
|
|
4138
5036
|
|
|
4139
|
-
private static void
|
|
4140
|
-
|
|
4141
|
-
Dictionary<
|
|
4142
|
-
InstanceId,
|
|
4143
|
-
Dictionary<int, HandlerActionCache<Action<T>>>
|
|
4144
|
-
> handlersByContext,
|
|
5037
|
+
private static void RunHandlers<TMessage>(
|
|
5038
|
+
Dictionary<int, HandlerActionCache<Action<T>>> sortedHandlers,
|
|
4145
5039
|
ref TMessage message,
|
|
4146
5040
|
int priority,
|
|
4147
5041
|
long emissionId
|
|
4148
5042
|
)
|
|
4149
5043
|
where TMessage : IMessage
|
|
4150
5044
|
{
|
|
4151
|
-
if (
|
|
4152
|
-
handlersByContext is not { Count: > 0 }
|
|
4153
|
-
|| !handlersByContext.TryGetValue(
|
|
4154
|
-
context,
|
|
4155
|
-
out Dictionary<int, HandlerActionCache<Action<T>>> cache
|
|
4156
|
-
)
|
|
4157
|
-
)
|
|
5045
|
+
if (sortedHandlers is not { Count: > 0 })
|
|
4158
5046
|
{
|
|
4159
5047
|
return;
|
|
4160
5048
|
}
|
|
4161
5049
|
|
|
4162
|
-
|
|
5050
|
+
if (!sortedHandlers.TryGetValue(priority, out HandlerActionCache<Action<T>> cache))
|
|
5051
|
+
{
|
|
5052
|
+
return;
|
|
5053
|
+
}
|
|
5054
|
+
|
|
5055
|
+
List<Action<T>> handlers = GetOrAddNewHandlerStack(cache, emissionId);
|
|
5056
|
+
ref T typedMessage = ref DxUnsafe.As<TMessage, T>(ref message);
|
|
5057
|
+
int handlersCount = handlers.Count;
|
|
5058
|
+
switch (handlersCount)
|
|
5059
|
+
{
|
|
5060
|
+
case 1:
|
|
5061
|
+
{
|
|
5062
|
+
handlers[0](typedMessage);
|
|
5063
|
+
return;
|
|
5064
|
+
}
|
|
5065
|
+
case 2:
|
|
5066
|
+
{
|
|
5067
|
+
handlers[0](typedMessage);
|
|
5068
|
+
if (handlers.Count < 2)
|
|
5069
|
+
{
|
|
5070
|
+
return;
|
|
5071
|
+
}
|
|
5072
|
+
handlers[1](typedMessage);
|
|
5073
|
+
return;
|
|
5074
|
+
}
|
|
5075
|
+
case 3:
|
|
5076
|
+
{
|
|
5077
|
+
handlers[0](typedMessage);
|
|
5078
|
+
if (handlers.Count < 2)
|
|
5079
|
+
{
|
|
5080
|
+
return;
|
|
5081
|
+
}
|
|
5082
|
+
handlers[1](typedMessage);
|
|
5083
|
+
if (handlers.Count < 3)
|
|
5084
|
+
{
|
|
5085
|
+
return;
|
|
5086
|
+
}
|
|
5087
|
+
handlers[2](typedMessage);
|
|
5088
|
+
return;
|
|
5089
|
+
}
|
|
5090
|
+
case 4:
|
|
5091
|
+
{
|
|
5092
|
+
handlers[0](typedMessage);
|
|
5093
|
+
if (handlers.Count < 2)
|
|
5094
|
+
{
|
|
5095
|
+
return;
|
|
5096
|
+
}
|
|
5097
|
+
handlers[1](typedMessage);
|
|
5098
|
+
if (handlers.Count < 3)
|
|
5099
|
+
{
|
|
5100
|
+
return;
|
|
5101
|
+
}
|
|
5102
|
+
handlers[2](typedMessage);
|
|
5103
|
+
if (handlers.Count < 4)
|
|
5104
|
+
{
|
|
5105
|
+
return;
|
|
5106
|
+
}
|
|
5107
|
+
handlers[3](typedMessage);
|
|
5108
|
+
return;
|
|
5109
|
+
}
|
|
5110
|
+
case 5:
|
|
5111
|
+
{
|
|
5112
|
+
handlers[0](typedMessage);
|
|
5113
|
+
if (handlers.Count < 2)
|
|
5114
|
+
{
|
|
5115
|
+
return;
|
|
5116
|
+
}
|
|
5117
|
+
handlers[1](typedMessage);
|
|
5118
|
+
if (handlers.Count < 3)
|
|
5119
|
+
{
|
|
5120
|
+
return;
|
|
5121
|
+
}
|
|
5122
|
+
handlers[2](typedMessage);
|
|
5123
|
+
if (handlers.Count < 4)
|
|
5124
|
+
{
|
|
5125
|
+
return;
|
|
5126
|
+
}
|
|
5127
|
+
handlers[3](typedMessage);
|
|
5128
|
+
if (handlers.Count < 5)
|
|
5129
|
+
{
|
|
5130
|
+
return;
|
|
5131
|
+
}
|
|
5132
|
+
handlers[4](typedMessage);
|
|
5133
|
+
return;
|
|
5134
|
+
}
|
|
5135
|
+
}
|
|
5136
|
+
|
|
5137
|
+
for (int i = 0; i < handlersCount && i < handlers.Count; ++i)
|
|
5138
|
+
{
|
|
5139
|
+
handlers[i](typedMessage);
|
|
5140
|
+
}
|
|
4163
5141
|
}
|
|
4164
5142
|
|
|
4165
5143
|
private static void RunHandlers<TMessage>(
|
|
4166
|
-
|
|
5144
|
+
ref InstanceId context,
|
|
5145
|
+
Dictionary<int, IHandlerActionCache> handlers,
|
|
4167
5146
|
ref TMessage message,
|
|
4168
5147
|
int priority,
|
|
4169
5148
|
long emissionId
|
|
4170
5149
|
)
|
|
4171
5150
|
where TMessage : IMessage
|
|
4172
5151
|
{
|
|
4173
|
-
if (
|
|
5152
|
+
if (handlers is not { Count: > 0 })
|
|
4174
5153
|
{
|
|
4175
5154
|
return;
|
|
4176
5155
|
}
|
|
4177
5156
|
|
|
4178
|
-
if (
|
|
5157
|
+
if (
|
|
5158
|
+
!handlers.TryGetValue(priority, out IHandlerActionCache erasedCache)
|
|
5159
|
+
|| erasedCache is not HandlerActionCache<Action<InstanceId, T>> cache
|
|
5160
|
+
)
|
|
4179
5161
|
{
|
|
4180
5162
|
return;
|
|
4181
5163
|
}
|
|
4182
5164
|
|
|
4183
|
-
List<Action<T>>
|
|
4184
|
-
|
|
4185
|
-
|
|
5165
|
+
List<Action<InstanceId, T>> typedHandlers = GetOrAddNewHandlerStack(
|
|
5166
|
+
cache,
|
|
5167
|
+
emissionId
|
|
5168
|
+
);
|
|
5169
|
+
ref T typedMessage = ref DxUnsafe.As<TMessage, T>(ref message);
|
|
5170
|
+
int handlersCount = typedHandlers.Count;
|
|
4186
5171
|
switch (handlersCount)
|
|
4187
5172
|
{
|
|
4188
5173
|
case 1:
|
|
4189
5174
|
{
|
|
4190
|
-
|
|
5175
|
+
typedHandlers[0](context, typedMessage);
|
|
4191
5176
|
return;
|
|
4192
5177
|
}
|
|
4193
5178
|
case 2:
|
|
4194
5179
|
{
|
|
4195
|
-
|
|
4196
|
-
|
|
5180
|
+
typedHandlers[0](context, typedMessage);
|
|
5181
|
+
if (typedHandlers.Count < 2)
|
|
5182
|
+
{
|
|
5183
|
+
return;
|
|
5184
|
+
}
|
|
5185
|
+
typedHandlers[1](context, typedMessage);
|
|
4197
5186
|
return;
|
|
4198
5187
|
}
|
|
4199
5188
|
case 3:
|
|
4200
5189
|
{
|
|
4201
|
-
|
|
4202
|
-
|
|
4203
|
-
|
|
5190
|
+
typedHandlers[0](context, typedMessage);
|
|
5191
|
+
if (typedHandlers.Count < 2)
|
|
5192
|
+
{
|
|
5193
|
+
return;
|
|
5194
|
+
}
|
|
5195
|
+
typedHandlers[1](context, typedMessage);
|
|
5196
|
+
if (typedHandlers.Count < 3)
|
|
5197
|
+
{
|
|
5198
|
+
return;
|
|
5199
|
+
}
|
|
5200
|
+
typedHandlers[2](context, typedMessage);
|
|
4204
5201
|
return;
|
|
4205
5202
|
}
|
|
4206
5203
|
case 4:
|
|
4207
5204
|
{
|
|
4208
|
-
|
|
4209
|
-
|
|
4210
|
-
|
|
4211
|
-
|
|
5205
|
+
typedHandlers[0](context, typedMessage);
|
|
5206
|
+
if (typedHandlers.Count < 2)
|
|
5207
|
+
{
|
|
5208
|
+
return;
|
|
5209
|
+
}
|
|
5210
|
+
typedHandlers[1](context, typedMessage);
|
|
5211
|
+
if (typedHandlers.Count < 3)
|
|
5212
|
+
{
|
|
5213
|
+
return;
|
|
5214
|
+
}
|
|
5215
|
+
typedHandlers[2](context, typedMessage);
|
|
5216
|
+
if (typedHandlers.Count < 4)
|
|
5217
|
+
{
|
|
5218
|
+
return;
|
|
5219
|
+
}
|
|
5220
|
+
typedHandlers[3](context, typedMessage);
|
|
4212
5221
|
return;
|
|
4213
5222
|
}
|
|
4214
5223
|
case 5:
|
|
4215
5224
|
{
|
|
4216
|
-
|
|
4217
|
-
|
|
4218
|
-
|
|
4219
|
-
|
|
4220
|
-
|
|
5225
|
+
typedHandlers[0](context, typedMessage);
|
|
5226
|
+
if (typedHandlers.Count < 2)
|
|
5227
|
+
{
|
|
5228
|
+
return;
|
|
5229
|
+
}
|
|
5230
|
+
typedHandlers[1](context, typedMessage);
|
|
5231
|
+
if (typedHandlers.Count < 3)
|
|
5232
|
+
{
|
|
5233
|
+
return;
|
|
5234
|
+
}
|
|
5235
|
+
typedHandlers[2](context, typedMessage);
|
|
5236
|
+
if (typedHandlers.Count < 4)
|
|
5237
|
+
{
|
|
5238
|
+
return;
|
|
5239
|
+
}
|
|
5240
|
+
typedHandlers[3](context, typedMessage);
|
|
5241
|
+
if (typedHandlers.Count < 5)
|
|
5242
|
+
{
|
|
5243
|
+
return;
|
|
5244
|
+
}
|
|
5245
|
+
typedHandlers[4](context, typedMessage);
|
|
4221
5246
|
return;
|
|
4222
5247
|
}
|
|
4223
5248
|
}
|
|
4224
5249
|
|
|
4225
|
-
for (int i = 0; i < handlersCount; ++i)
|
|
5250
|
+
for (int i = 0; i < handlersCount && i < typedHandlers.Count; ++i)
|
|
4226
5251
|
{
|
|
4227
|
-
|
|
5252
|
+
typedHandlers[i](context, typedMessage);
|
|
4228
5253
|
}
|
|
4229
5254
|
}
|
|
4230
5255
|
|
|
@@ -4256,7 +5281,7 @@ namespace DxMessaging.Core
|
|
|
4256
5281
|
cache,
|
|
4257
5282
|
emissionId
|
|
4258
5283
|
);
|
|
4259
|
-
ref T typedMessage = ref
|
|
5284
|
+
ref T typedMessage = ref DxUnsafe.As<TMessage, T>(ref message);
|
|
4260
5285
|
int handlersCount = typedHandlers.Count;
|
|
4261
5286
|
switch (handlersCount)
|
|
4262
5287
|
{
|
|
@@ -4268,60 +5293,124 @@ namespace DxMessaging.Core
|
|
|
4268
5293
|
case 2:
|
|
4269
5294
|
{
|
|
4270
5295
|
typedHandlers[0](context, typedMessage);
|
|
5296
|
+
if (typedHandlers.Count < 2)
|
|
5297
|
+
{
|
|
5298
|
+
return;
|
|
5299
|
+
}
|
|
4271
5300
|
typedHandlers[1](context, typedMessage);
|
|
4272
5301
|
return;
|
|
4273
5302
|
}
|
|
4274
5303
|
case 3:
|
|
4275
5304
|
{
|
|
4276
5305
|
typedHandlers[0](context, typedMessage);
|
|
5306
|
+
if (typedHandlers.Count < 2)
|
|
5307
|
+
{
|
|
5308
|
+
return;
|
|
5309
|
+
}
|
|
4277
5310
|
typedHandlers[1](context, typedMessage);
|
|
5311
|
+
if (typedHandlers.Count < 3)
|
|
5312
|
+
{
|
|
5313
|
+
return;
|
|
5314
|
+
}
|
|
4278
5315
|
typedHandlers[2](context, typedMessage);
|
|
4279
5316
|
return;
|
|
4280
5317
|
}
|
|
4281
5318
|
case 4:
|
|
4282
5319
|
{
|
|
4283
5320
|
typedHandlers[0](context, typedMessage);
|
|
5321
|
+
if (typedHandlers.Count < 2)
|
|
5322
|
+
{
|
|
5323
|
+
return;
|
|
5324
|
+
}
|
|
4284
5325
|
typedHandlers[1](context, typedMessage);
|
|
5326
|
+
if (typedHandlers.Count < 3)
|
|
5327
|
+
{
|
|
5328
|
+
return;
|
|
5329
|
+
}
|
|
4285
5330
|
typedHandlers[2](context, typedMessage);
|
|
5331
|
+
if (typedHandlers.Count < 4)
|
|
5332
|
+
{
|
|
5333
|
+
return;
|
|
5334
|
+
}
|
|
4286
5335
|
typedHandlers[3](context, typedMessage);
|
|
4287
5336
|
return;
|
|
4288
5337
|
}
|
|
4289
5338
|
case 5:
|
|
4290
5339
|
{
|
|
4291
5340
|
typedHandlers[0](context, typedMessage);
|
|
5341
|
+
if (typedHandlers.Count < 2)
|
|
5342
|
+
{
|
|
5343
|
+
return;
|
|
5344
|
+
}
|
|
4292
5345
|
typedHandlers[1](context, typedMessage);
|
|
5346
|
+
if (typedHandlers.Count < 3)
|
|
5347
|
+
{
|
|
5348
|
+
return;
|
|
5349
|
+
}
|
|
4293
5350
|
typedHandlers[2](context, typedMessage);
|
|
5351
|
+
if (typedHandlers.Count < 4)
|
|
5352
|
+
{
|
|
5353
|
+
return;
|
|
5354
|
+
}
|
|
4294
5355
|
typedHandlers[3](context, typedMessage);
|
|
5356
|
+
if (typedHandlers.Count < 5)
|
|
5357
|
+
{
|
|
5358
|
+
return;
|
|
5359
|
+
}
|
|
4295
5360
|
typedHandlers[4](context, typedMessage);
|
|
4296
5361
|
return;
|
|
4297
5362
|
}
|
|
4298
5363
|
}
|
|
4299
5364
|
|
|
4300
|
-
for (int i = 0; i < handlersCount; ++i)
|
|
5365
|
+
for (int i = 0; i < handlersCount && i < typedHandlers.Count; ++i)
|
|
4301
5366
|
{
|
|
4302
5367
|
typedHandlers[i](context, typedMessage);
|
|
4303
5368
|
}
|
|
4304
5369
|
}
|
|
4305
5370
|
|
|
5371
|
+
// Mid-dispatch clear contract: the List returned here is the LIVE
|
|
5372
|
+
// cache.cache list, not a copy. IHandlerActionCache.Reset() (bus
|
|
5373
|
+
// reset / sweep eviction) clears it IN PLACE, so every dispatch
|
|
5374
|
+
// loop that indexes the returned list re-checks list.Count before
|
|
5375
|
+
// each invocation past the first (and the >5 fallback loops bound
|
|
5376
|
+
// on the live Count). A reset fired from inside a handler then
|
|
5377
|
+
// cleanly stops the in-flight bucket: no peer delegate runs and
|
|
5378
|
+
// nothing throws. The re-check is a single inlined List.Count
|
|
5379
|
+
// field read on data already in cache, so steady-state dispatch
|
|
5380
|
+
// cost is unchanged.
|
|
4306
5381
|
internal static List<TU> GetOrAddNewHandlerStack<TU>(
|
|
4307
5382
|
HandlerActionCache<TU> actionCache,
|
|
4308
5383
|
long emissionId
|
|
4309
5384
|
)
|
|
4310
5385
|
{
|
|
5386
|
+
DebugAssertInsertionOrderInSync(actionCache);
|
|
4311
5387
|
if (actionCache.lastSeenEmissionId != emissionId)
|
|
4312
5388
|
{
|
|
4313
5389
|
if (actionCache.version != actionCache.lastSeenVersion)
|
|
4314
5390
|
{
|
|
5391
|
+
// Rebuild the dispatch snapshot from insertionOrder, NOT from
|
|
5392
|
+
// the entries dictionary: dictionary enumeration order permutes
|
|
5393
|
+
// after Remove/Add churn (freed slots are reused LIFO), while
|
|
5394
|
+
// insertionOrder preserves the documented first-registration
|
|
5395
|
+
// order for equal-priority handlers. This branch only runs on
|
|
5396
|
+
// registration churn (version bump), never on steady-state
|
|
5397
|
+
// dispatch, and allocates nothing (the pooled cache list is
|
|
5398
|
+
// cleared and refilled in place).
|
|
4315
5399
|
List<TU> list = actionCache.cache;
|
|
4316
5400
|
list.Clear();
|
|
4317
|
-
|
|
4318
|
-
|
|
4319
|
-
|
|
4320
|
-
HandlerActionCache<TU>.Entry
|
|
4321
|
-
> kvp in actionCache.entries
|
|
4322
|
-
)
|
|
5401
|
+
List<TU> orderedHandlers = actionCache.insertionOrder;
|
|
5402
|
+
int orderedCount = orderedHandlers.Count;
|
|
5403
|
+
for (int i = 0; i < orderedCount; ++i)
|
|
4323
5404
|
{
|
|
4324
|
-
|
|
5405
|
+
if (
|
|
5406
|
+
actionCache.entries.TryGetValue(
|
|
5407
|
+
orderedHandlers[i],
|
|
5408
|
+
out HandlerActionCache<TU>.Entry entry
|
|
5409
|
+
)
|
|
5410
|
+
)
|
|
5411
|
+
{
|
|
5412
|
+
list.Add(entry.handler);
|
|
5413
|
+
}
|
|
4325
5414
|
}
|
|
4326
5415
|
actionCache.lastSeenVersion = actionCache.version;
|
|
4327
5416
|
}
|
|
@@ -4330,20 +5419,126 @@ namespace DxMessaging.Core
|
|
|
4330
5419
|
return actionCache.cache;
|
|
4331
5420
|
}
|
|
4332
5421
|
|
|
4333
|
-
|
|
4334
|
-
|
|
4335
|
-
|
|
4336
|
-
|
|
5422
|
+
// Asserts insertionOrder stays in lockstep with the entries
|
|
5423
|
+
// dictionary at every dispatch-snapshot read. Drift indicates a
|
|
5424
|
+
// mutation site of HandlerActionCache.entries that forgot to
|
|
5425
|
+
// mirror the change into insertionOrder (AddHandler* family,
|
|
5426
|
+
// deregistration closures, IHandlerActionCache.Reset). Stripped
|
|
5427
|
+
// in Release builds via [Conditional("DEBUG")] -- zero hot-path
|
|
5428
|
+
// cost.
|
|
5429
|
+
[Conditional("DEBUG")]
|
|
5430
|
+
private static void DebugAssertInsertionOrderInSync<TU>(
|
|
5431
|
+
HandlerActionCache<TU> actionCache
|
|
5432
|
+
)
|
|
5433
|
+
{
|
|
5434
|
+
System.Diagnostics.Debug.Assert(
|
|
5435
|
+
actionCache.insertionOrder.Count == actionCache.entries.Count,
|
|
5436
|
+
"HandlerActionCache.insertionOrder must mirror entries: every first "
|
|
5437
|
+
+ "registration appends and every final deregistration removes. A "
|
|
5438
|
+
+ "count mismatch means a mutation site skipped the insertionOrder "
|
|
5439
|
+
+ "update and same-priority dispatch order is no longer trustworthy."
|
|
5440
|
+
);
|
|
5441
|
+
}
|
|
5442
|
+
|
|
5443
|
+
private static Action AddHandler<TU>(
|
|
5444
|
+
TypedGlobalSlot slot,
|
|
5445
|
+
TU originalHandler,
|
|
5446
|
+
TU augmentedHandler,
|
|
5447
|
+
Action deregistration,
|
|
5448
|
+
IMessageBus messageBus
|
|
4337
5449
|
)
|
|
4338
5450
|
{
|
|
5451
|
+
slot.lastTouchTicks =
|
|
5452
|
+
global::DxMessaging.Core.MessageBus.MessageBus.GetCurrentTouchTick(messageBus);
|
|
5453
|
+
HandlerActionCache<TU> cache = slot.cache as HandlerActionCache<TU>;
|
|
5454
|
+
if (cache == null)
|
|
5455
|
+
{
|
|
5456
|
+
cache = new HandlerActionCache<TU>();
|
|
5457
|
+
slot.cache = cache;
|
|
5458
|
+
}
|
|
5459
|
+
|
|
4339
5460
|
if (
|
|
4340
|
-
|
|
4341
|
-
|
|
5461
|
+
!cache.entries.TryGetValue(
|
|
5462
|
+
originalHandler,
|
|
5463
|
+
out HandlerActionCache<TU>.Entry entry
|
|
5464
|
+
)
|
|
4342
5465
|
)
|
|
4343
5466
|
{
|
|
4344
|
-
|
|
4345
|
-
|
|
5467
|
+
entry = new HandlerActionCache<TU>.Entry(augmentedHandler, 0);
|
|
5468
|
+
}
|
|
5469
|
+
|
|
5470
|
+
bool firstRegistration = entry.count == 0;
|
|
5471
|
+
entry = firstRegistration
|
|
5472
|
+
? new HandlerActionCache<TU>.Entry(augmentedHandler, 1)
|
|
5473
|
+
: new HandlerActionCache<TU>.Entry(entry.handler, entry.count + 1);
|
|
5474
|
+
|
|
5475
|
+
cache.entries[originalHandler] = entry;
|
|
5476
|
+
if (firstRegistration)
|
|
5477
|
+
{
|
|
5478
|
+
cache.insertionOrder.Add(originalHandler);
|
|
4346
5479
|
}
|
|
5480
|
+
cache.version++;
|
|
5481
|
+
if (firstRegistration)
|
|
5482
|
+
{
|
|
5483
|
+
slot.liveCount++;
|
|
5484
|
+
}
|
|
5485
|
+
|
|
5486
|
+
HandlerActionCache<TU> localCache = cache;
|
|
5487
|
+
TypedGlobalSlot localSlot = slot;
|
|
5488
|
+
long localSlotVersion = slot.version;
|
|
5489
|
+
long localResetGeneration =
|
|
5490
|
+
global::DxMessaging.Core.MessageBus.MessageBus.GetResetGeneration(messageBus);
|
|
5491
|
+
|
|
5492
|
+
return () =>
|
|
5493
|
+
{
|
|
5494
|
+
if (
|
|
5495
|
+
!global::DxMessaging.Core.MessageBus.MessageBus.IsResetGenerationCurrent(
|
|
5496
|
+
messageBus,
|
|
5497
|
+
localResetGeneration
|
|
5498
|
+
)
|
|
5499
|
+
)
|
|
5500
|
+
{
|
|
5501
|
+
return;
|
|
5502
|
+
}
|
|
5503
|
+
|
|
5504
|
+
if (localSlot.version != localSlotVersion)
|
|
5505
|
+
{
|
|
5506
|
+
return;
|
|
5507
|
+
}
|
|
5508
|
+
|
|
5509
|
+
if (
|
|
5510
|
+
!localCache.entries.TryGetValue(
|
|
5511
|
+
originalHandler,
|
|
5512
|
+
out HandlerActionCache<TU>.Entry localEntry
|
|
5513
|
+
)
|
|
5514
|
+
)
|
|
5515
|
+
{
|
|
5516
|
+
return;
|
|
5517
|
+
}
|
|
5518
|
+
|
|
5519
|
+
localCache.version++;
|
|
5520
|
+
|
|
5521
|
+
deregistration?.Invoke();
|
|
5522
|
+
localSlot.lastTouchTicks =
|
|
5523
|
+
global::DxMessaging.Core.MessageBus.MessageBus.GetCurrentTouchTick(
|
|
5524
|
+
messageBus
|
|
5525
|
+
);
|
|
5526
|
+
|
|
5527
|
+
if (localEntry.count <= 1)
|
|
5528
|
+
{
|
|
5529
|
+
_ = localCache.entries.Remove(originalHandler);
|
|
5530
|
+
_ = localCache.insertionOrder.Remove(originalHandler);
|
|
5531
|
+
localCache.version++;
|
|
5532
|
+
localSlot.liveCount--;
|
|
5533
|
+
return;
|
|
5534
|
+
}
|
|
5535
|
+
|
|
5536
|
+
localEntry = new HandlerActionCache<TU>.Entry(
|
|
5537
|
+
localEntry.handler,
|
|
5538
|
+
localEntry.count - 1
|
|
5539
|
+
);
|
|
5540
|
+
localCache.entries[originalHandler] = localEntry;
|
|
5541
|
+
};
|
|
4347
5542
|
}
|
|
4348
5543
|
|
|
4349
5544
|
private static Action AddHandler<TU>(
|
|
@@ -4356,7 +5551,7 @@ namespace DxMessaging.Core
|
|
|
4356
5551
|
TU augmentedHandler,
|
|
4357
5552
|
Action deregistration,
|
|
4358
5553
|
int priority,
|
|
4359
|
-
|
|
5554
|
+
IMessageBus messageBus
|
|
4360
5555
|
)
|
|
4361
5556
|
{
|
|
4362
5557
|
handlersByContext ??=
|
|
@@ -4395,6 +5590,10 @@ namespace DxMessaging.Core
|
|
|
4395
5590
|
: new HandlerActionCache<TU>.Entry(entry.handler, entry.count + 1);
|
|
4396
5591
|
|
|
4397
5592
|
cache.entries[originalHandler] = entry;
|
|
5593
|
+
if (firstRegistration)
|
|
5594
|
+
{
|
|
5595
|
+
cache.insertionOrder.Add(originalHandler);
|
|
5596
|
+
}
|
|
4398
5597
|
cache.version++;
|
|
4399
5598
|
|
|
4400
5599
|
Dictionary<
|
|
@@ -4433,6 +5632,7 @@ namespace DxMessaging.Core
|
|
|
4433
5632
|
if (localEntry.count <= 1)
|
|
4434
5633
|
{
|
|
4435
5634
|
_ = localCache.entries.Remove(originalHandler);
|
|
5635
|
+
_ = localCache.insertionOrder.Remove(originalHandler);
|
|
4436
5636
|
localCache.version++;
|
|
4437
5637
|
if (localCache.entries.Count == 0)
|
|
4438
5638
|
{
|
|
@@ -4480,6 +5680,10 @@ namespace DxMessaging.Core
|
|
|
4480
5680
|
: new HandlerActionCache<TU>.Entry(entry.handler, entry.count + 1);
|
|
4481
5681
|
|
|
4482
5682
|
cache.entries[originalHandler] = entry;
|
|
5683
|
+
if (firstRegistration)
|
|
5684
|
+
{
|
|
5685
|
+
cache.insertionOrder.Add(originalHandler);
|
|
5686
|
+
}
|
|
4483
5687
|
cache.version++;
|
|
4484
5688
|
|
|
4485
5689
|
HandlerActionCache<TU> localCache = cache;
|
|
@@ -4503,6 +5707,7 @@ namespace DxMessaging.Core
|
|
|
4503
5707
|
if (localEntry.count <= 1)
|
|
4504
5708
|
{
|
|
4505
5709
|
_ = localCache.entries.Remove(originalHandler);
|
|
5710
|
+
_ = localCache.insertionOrder.Remove(originalHandler);
|
|
4506
5711
|
localCache.version++;
|
|
4507
5712
|
return;
|
|
4508
5713
|
}
|
|
@@ -4548,6 +5753,10 @@ namespace DxMessaging.Core
|
|
|
4548
5753
|
: new HandlerActionCache<TU>.Entry(entry.handler, entry.count + 1);
|
|
4549
5754
|
|
|
4550
5755
|
cache.entries[originalHandler] = entry;
|
|
5756
|
+
if (firstRegistration)
|
|
5757
|
+
{
|
|
5758
|
+
cache.insertionOrder.Add(originalHandler);
|
|
5759
|
+
}
|
|
4551
5760
|
cache.version++;
|
|
4552
5761
|
|
|
4553
5762
|
Dictionary<int, HandlerActionCache<TU>> localHandlers = handlers;
|
|
@@ -4576,6 +5785,7 @@ namespace DxMessaging.Core
|
|
|
4576
5785
|
if (localEntry.count <= 1)
|
|
4577
5786
|
{
|
|
4578
5787
|
_ = localCache.entries.Remove(originalHandler);
|
|
5788
|
+
_ = localCache.insertionOrder.Remove(originalHandler);
|
|
4579
5789
|
localCache.version++;
|
|
4580
5790
|
if (localCache.entries.Count == 0)
|
|
4581
5791
|
{
|
|
@@ -4597,6 +5807,148 @@ namespace DxMessaging.Core
|
|
|
4597
5807
|
// Variant of AddHandler that preserves the priority key in the dictionary when the last entry is removed.
|
|
4598
5808
|
// This ensures that during an in-flight emission (where handler stacks are already frozen),
|
|
4599
5809
|
// subsequent removals do not cause lookups to fail for the current pass.
|
|
5810
|
+
// `flatInvoker` carries the pre-resolved flat-dispatch invoker for
|
|
5811
|
+
// registrations the bus-side flat snapshot consumes (untargeted
|
|
5812
|
+
// handle/post default handlers); see HandlerActionCache.Entry.flatInvoker.
|
|
5813
|
+
private Action AddHandlerPreservingPriorityKey<TU>(
|
|
5814
|
+
Dictionary<int, IHandlerActionCache> handlers,
|
|
5815
|
+
TU originalHandler,
|
|
5816
|
+
TU augmentedHandler,
|
|
5817
|
+
Action deregistration,
|
|
5818
|
+
int priority,
|
|
5819
|
+
IMessageBus messageBus,
|
|
5820
|
+
object flatInvoker = null
|
|
5821
|
+
)
|
|
5822
|
+
{
|
|
5823
|
+
if (
|
|
5824
|
+
!handlers.TryGetValue(priority, out IHandlerActionCache erasedCache)
|
|
5825
|
+
|| erasedCache is not HandlerActionCache<TU> cache
|
|
5826
|
+
)
|
|
5827
|
+
{
|
|
5828
|
+
cache = new HandlerActionCache<TU>();
|
|
5829
|
+
handlers[priority] = cache;
|
|
5830
|
+
}
|
|
5831
|
+
|
|
5832
|
+
if (
|
|
5833
|
+
!cache.entries.TryGetValue(
|
|
5834
|
+
originalHandler,
|
|
5835
|
+
out HandlerActionCache<TU>.Entry entry
|
|
5836
|
+
)
|
|
5837
|
+
)
|
|
5838
|
+
{
|
|
5839
|
+
entry = new HandlerActionCache<TU>.Entry(augmentedHandler, 0);
|
|
5840
|
+
}
|
|
5841
|
+
|
|
5842
|
+
bool firstRegistration = entry.count == 0;
|
|
5843
|
+
entry = firstRegistration
|
|
5844
|
+
? new HandlerActionCache<TU>.Entry(augmentedHandler, 1, flatInvoker)
|
|
5845
|
+
: new HandlerActionCache<TU>.Entry(
|
|
5846
|
+
entry.handler,
|
|
5847
|
+
entry.count + 1,
|
|
5848
|
+
entry.flatInvoker
|
|
5849
|
+
);
|
|
5850
|
+
|
|
5851
|
+
cache.entries[originalHandler] = entry;
|
|
5852
|
+
if (firstRegistration)
|
|
5853
|
+
{
|
|
5854
|
+
cache.insertionOrder.Add(originalHandler);
|
|
5855
|
+
}
|
|
5856
|
+
cache.version++;
|
|
5857
|
+
TypedSlot<T> slot = FindPrioritySlot(handlers);
|
|
5858
|
+
if (slot != null)
|
|
5859
|
+
{
|
|
5860
|
+
slot.lastTouchTicks =
|
|
5861
|
+
global::DxMessaging.Core.MessageBus.MessageBus.GetCurrentTouchTick(
|
|
5862
|
+
messageBus
|
|
5863
|
+
);
|
|
5864
|
+
}
|
|
5865
|
+
if (slot != null && !slot.orderedPriorities.Contains(priority))
|
|
5866
|
+
{
|
|
5867
|
+
slot.orderedPriorities.Add(priority);
|
|
5868
|
+
}
|
|
5869
|
+
if (firstRegistration && slot != null)
|
|
5870
|
+
{
|
|
5871
|
+
slot.liveCount++;
|
|
5872
|
+
}
|
|
5873
|
+
|
|
5874
|
+
Dictionary<int, IHandlerActionCache> localHandlers = handlers;
|
|
5875
|
+
TypedSlot<T> localSlot = slot;
|
|
5876
|
+
long localSlotVersion = slot?.version ?? 0;
|
|
5877
|
+
long localResetGeneration =
|
|
5878
|
+
global::DxMessaging.Core.MessageBus.MessageBus.GetResetGeneration(messageBus);
|
|
5879
|
+
|
|
5880
|
+
return () =>
|
|
5881
|
+
{
|
|
5882
|
+
if (
|
|
5883
|
+
!global::DxMessaging.Core.MessageBus.MessageBus.IsResetGenerationCurrent(
|
|
5884
|
+
messageBus,
|
|
5885
|
+
localResetGeneration
|
|
5886
|
+
)
|
|
5887
|
+
)
|
|
5888
|
+
{
|
|
5889
|
+
return;
|
|
5890
|
+
}
|
|
5891
|
+
|
|
5892
|
+
if (localSlot != null && localSlot.version != localSlotVersion)
|
|
5893
|
+
{
|
|
5894
|
+
return;
|
|
5895
|
+
}
|
|
5896
|
+
|
|
5897
|
+
if (
|
|
5898
|
+
!localHandlers.TryGetValue(
|
|
5899
|
+
priority,
|
|
5900
|
+
out IHandlerActionCache localErasedCache
|
|
5901
|
+
) || localErasedCache is not HandlerActionCache<TU> localCache
|
|
5902
|
+
)
|
|
5903
|
+
{
|
|
5904
|
+
return;
|
|
5905
|
+
}
|
|
5906
|
+
|
|
5907
|
+
if (
|
|
5908
|
+
!localCache.entries.TryGetValue(
|
|
5909
|
+
originalHandler,
|
|
5910
|
+
out HandlerActionCache<TU>.Entry localEntry
|
|
5911
|
+
)
|
|
5912
|
+
)
|
|
5913
|
+
{
|
|
5914
|
+
return;
|
|
5915
|
+
}
|
|
5916
|
+
|
|
5917
|
+
localCache.version++;
|
|
5918
|
+
|
|
5919
|
+
deregistration?.Invoke();
|
|
5920
|
+
if (localSlot != null)
|
|
5921
|
+
{
|
|
5922
|
+
localSlot.lastTouchTicks =
|
|
5923
|
+
global::DxMessaging.Core.MessageBus.MessageBus.GetCurrentTouchTick(
|
|
5924
|
+
messageBus
|
|
5925
|
+
);
|
|
5926
|
+
}
|
|
5927
|
+
|
|
5928
|
+
if (localEntry.count <= 1)
|
|
5929
|
+
{
|
|
5930
|
+
_ = localCache.entries.Remove(originalHandler);
|
|
5931
|
+
_ = localCache.insertionOrder.Remove(originalHandler);
|
|
5932
|
+
localCache.version++;
|
|
5933
|
+
if (localSlot != null)
|
|
5934
|
+
{
|
|
5935
|
+
localSlot.liveCount--;
|
|
5936
|
+
}
|
|
5937
|
+
// Intentionally DO NOT remove the priority key here to preserve
|
|
5938
|
+
// the cache handle during an in-flight emission.
|
|
5939
|
+
return;
|
|
5940
|
+
}
|
|
5941
|
+
|
|
5942
|
+
localEntry = new HandlerActionCache<TU>.Entry(
|
|
5943
|
+
localEntry.handler,
|
|
5944
|
+
localEntry.count - 1,
|
|
5945
|
+
localEntry.flatInvoker
|
|
5946
|
+
);
|
|
5947
|
+
|
|
5948
|
+
localCache.entries[originalHandler] = localEntry;
|
|
5949
|
+
};
|
|
5950
|
+
}
|
|
5951
|
+
|
|
4600
5952
|
private static Action AddHandlerPreservingPriorityKey<TU>(
|
|
4601
5953
|
ref Dictionary<int, HandlerActionCache<TU>> handlers,
|
|
4602
5954
|
TU originalHandler,
|
|
@@ -4630,6 +5982,10 @@ namespace DxMessaging.Core
|
|
|
4630
5982
|
: new HandlerActionCache<TU>.Entry(entry.handler, entry.count + 1);
|
|
4631
5983
|
|
|
4632
5984
|
cache.entries[originalHandler] = entry;
|
|
5985
|
+
if (firstRegistration)
|
|
5986
|
+
{
|
|
5987
|
+
cache.insertionOrder.Add(originalHandler);
|
|
5988
|
+
}
|
|
4633
5989
|
cache.version++;
|
|
4634
5990
|
|
|
4635
5991
|
Dictionary<int, HandlerActionCache<TU>> localHandlers = handlers;
|
|
@@ -4658,6 +6014,7 @@ namespace DxMessaging.Core
|
|
|
4658
6014
|
if (localEntry.count <= 1)
|
|
4659
6015
|
{
|
|
4660
6016
|
_ = localCache.entries.Remove(originalHandler);
|
|
6017
|
+
_ = localCache.insertionOrder.Remove(originalHandler);
|
|
4661
6018
|
localCache.version++;
|
|
4662
6019
|
// Intentionally DO NOT remove the priority key here to preserve
|
|
4663
6020
|
// the cache handle during an in-flight emission.
|