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
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
namespace DxMessaging.Core.MessageBus.Internal
|
|
2
|
+
{
|
|
3
|
+
/// <summary>
|
|
4
|
+
/// First axis of the dispatch slot key. Identifies the structural shape of a
|
|
5
|
+
/// registration: untargeted scalar, targeted (per-recipient), broadcast
|
|
6
|
+
/// (per-source), or global (catch-all that subscribes to every emit of a
|
|
7
|
+
/// registered base shape).
|
|
8
|
+
/// </summary>
|
|
9
|
+
/// <remarks>
|
|
10
|
+
/// Encoded into <see cref="SlotKey.Packed"/> in the high nibble (bits 4-7).
|
|
11
|
+
/// Packed value range is 0..3, leaving room for two additional kinds before
|
|
12
|
+
/// the nibble overflows.
|
|
13
|
+
/// </remarks>
|
|
14
|
+
internal enum DispatchKind : byte
|
|
15
|
+
{
|
|
16
|
+
/// <summary>
|
|
17
|
+
/// Untargeted dispatch. No <see cref="InstanceId"/> recipient or source
|
|
18
|
+
/// carried; the message itself is the entire payload.
|
|
19
|
+
/// </summary>
|
|
20
|
+
Untargeted = 0,
|
|
21
|
+
|
|
22
|
+
/// <summary>Targeted dispatch. Message carries an <see cref="InstanceId"/> recipient.</summary>
|
|
23
|
+
Targeted = 1,
|
|
24
|
+
|
|
25
|
+
/// <summary>Broadcast dispatch. Message carries an <see cref="InstanceId"/> source.</summary>
|
|
26
|
+
Broadcast = 2,
|
|
27
|
+
|
|
28
|
+
/// <summary>
|
|
29
|
+
/// Reserved for the global-dispatch axis. Currently unreferenced -- the
|
|
30
|
+
/// global dispatch path uses <see cref="BusGlobalSlot"/> directly with the
|
|
31
|
+
/// per-message-shape <see cref="DispatchKind"/> (<see cref="Untargeted"/>,
|
|
32
|
+
/// <see cref="Targeted"/>, or <see cref="Broadcast"/>) rather than this
|
|
33
|
+
/// value. Kept to lock the bit-packing contract documented on
|
|
34
|
+
/// <see cref="SlotKey"/>.
|
|
35
|
+
/// </summary>
|
|
36
|
+
Global = 3,
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
namespace DxMessaging.Core.MessageBus.Internal
|
|
2
|
+
{
|
|
3
|
+
/// <summary>
|
|
4
|
+
/// Second axis of the dispatch slot key. Distinguishes the two phases of
|
|
5
|
+
/// message processing: the primary handle phase and the post-process phase
|
|
6
|
+
/// that runs after every primary handler has returned.
|
|
7
|
+
/// </summary>
|
|
8
|
+
/// <remarks>
|
|
9
|
+
/// Encoded into <see cref="SlotKey.Packed"/> at bit 3. Packed value range is
|
|
10
|
+
/// 0..1.
|
|
11
|
+
/// </remarks>
|
|
12
|
+
internal enum DispatchPhase : byte
|
|
13
|
+
{
|
|
14
|
+
/// <summary>Primary handler phase.</summary>
|
|
15
|
+
Handle = 0,
|
|
16
|
+
|
|
17
|
+
/// <summary>Post-processor phase. Runs after the handle phase completes.</summary>
|
|
18
|
+
PostProcess = 1,
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
namespace DxMessaging.Core.MessageBus.Internal
|
|
2
|
+
{
|
|
3
|
+
/// <summary>
|
|
4
|
+
/// Third axis of the dispatch slot key. Captures handler-shape variants that
|
|
5
|
+
/// share a <see cref="DispatchKind"/> but differ in delegate signature or
|
|
6
|
+
/// fast-path eligibility.
|
|
7
|
+
/// </summary>
|
|
8
|
+
/// <remarks>
|
|
9
|
+
/// Encoded into <see cref="SlotKey.Packed"/> in the low three bits (bits
|
|
10
|
+
/// 0-2). Packed value range is 0..3 in current usage; the three-bit slot
|
|
11
|
+
/// leaves room for four additional variants without disturbing the packed
|
|
12
|
+
/// layout.
|
|
13
|
+
/// </remarks>
|
|
14
|
+
internal enum DispatchVariant : byte
|
|
15
|
+
{
|
|
16
|
+
/// <summary>Default handler shape (full delegate signature with context).</summary>
|
|
17
|
+
Default = 0,
|
|
18
|
+
|
|
19
|
+
/// <summary>Fast-path handler shape (specialized signature).</summary>
|
|
20
|
+
Fast = 1,
|
|
21
|
+
|
|
22
|
+
/// <summary>Handler shape that elides the context argument.</summary>
|
|
23
|
+
WithoutContext = 2,
|
|
24
|
+
|
|
25
|
+
/// <summary>Fast-path handler shape that elides the context argument.</summary>
|
|
26
|
+
WithoutContextFast = 3,
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
namespace DxMessaging.Core.MessageBus.Internal
|
|
2
|
+
{
|
|
3
|
+
/// <summary>
|
|
4
|
+
/// Marker interface for bus-level slot containers that the eviction layer
|
|
5
|
+
/// can sweep. Each slot tracks its last-touch tick so the sweep can decide
|
|
6
|
+
/// whether to reclaim it, and exposes a monotonic
|
|
7
|
+
/// <see cref="Version"/> so that staged dispatch closures captured before
|
|
8
|
+
/// eviction can detect they have been invalidated.
|
|
9
|
+
/// </summary>
|
|
10
|
+
/// <remarks>
|
|
11
|
+
/// <see cref="Reset"/> returns inner pooled collections to
|
|
12
|
+
/// <c>DxMessaging.Core.Pooling.DxPools</c>. The sweep policy calls
|
|
13
|
+
/// <see cref="Reset"/> on idle empty slots.
|
|
14
|
+
/// </remarks>
|
|
15
|
+
internal interface IEvictableSlot
|
|
16
|
+
{
|
|
17
|
+
/// <summary>
|
|
18
|
+
/// The bus tick counter value at the most recent register / deregister /
|
|
19
|
+
/// emit operation that touched this slot. Used by the sweep to decide
|
|
20
|
+
/// whether the slot has been idle for long enough to evict.
|
|
21
|
+
/// </summary>
|
|
22
|
+
long LastTouchTicks { get; }
|
|
23
|
+
|
|
24
|
+
/// <summary>
|
|
25
|
+
/// True iff the slot currently retains zero live registrations. Cheap
|
|
26
|
+
/// (single integer compare); maintained at register / deregister sites.
|
|
27
|
+
/// Stale-but-non-empty slots are NOT eviction candidates -- only
|
|
28
|
+
/// idle AND empty slots are reclaimed.
|
|
29
|
+
/// </summary>
|
|
30
|
+
bool IsEmpty { get; }
|
|
31
|
+
|
|
32
|
+
/// <summary>
|
|
33
|
+
/// Strictly monotonic version counter. Bumped by <see cref="Reset"/>
|
|
34
|
+
/// (and by registration-time mutations on the slot). Allows captured
|
|
35
|
+
/// dispatch closures to detect post-eviction invalidation.
|
|
36
|
+
/// </summary>
|
|
37
|
+
long Version { get; }
|
|
38
|
+
|
|
39
|
+
/// <summary>
|
|
40
|
+
/// Reclaim this slot: clear inner state, return any pooled inner
|
|
41
|
+
/// collections to <c>DxPools</c>, and bump <see cref="Version"/>.
|
|
42
|
+
/// Idempotent. <see cref="LastTouchTicks"/> is intentionally preserved
|
|
43
|
+
/// across <see cref="Reset"/> so the sweep can distinguish freshly-reset
|
|
44
|
+
/// slots from never-touched ones.
|
|
45
|
+
/// </summary>
|
|
46
|
+
void Reset();
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
namespace DxMessaging.Core.MessageBus.Internal
|
|
2
|
+
{
|
|
3
|
+
using System;
|
|
4
|
+
|
|
5
|
+
/// <summary>
|
|
6
|
+
/// Describes a <see cref="DxMessaging.Core.MessageBus.MessageBus"/> cache storage field that
|
|
7
|
+
/// participates in explicit or idle sweep coverage.
|
|
8
|
+
/// </summary>
|
|
9
|
+
internal interface ISweepable
|
|
10
|
+
{
|
|
11
|
+
string StorageFieldName { get; }
|
|
12
|
+
Type StorageFieldType { get; }
|
|
13
|
+
int Sweep(DxMessaging.Core.MessageBus.MessageBus bus, bool force);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
namespace DxMessaging.Core.MessageBus.Internal
|
|
2
|
+
{
|
|
3
|
+
using System;
|
|
4
|
+
using System.Runtime.CompilerServices;
|
|
5
|
+
|
|
6
|
+
/// <summary>
|
|
7
|
+
/// Static lookup that translates a <see cref="RegistrationMethod"/> enum
|
|
8
|
+
/// value into the <see cref="SlotKey"/> coordinate that identifies the
|
|
9
|
+
/// dispatch slot it targets. Replaces the legacy 14-case category switch
|
|
10
|
+
/// with a data-driven table.
|
|
11
|
+
/// </summary>
|
|
12
|
+
/// <remarks>
|
|
13
|
+
/// <para>
|
|
14
|
+
/// Two registration methods --
|
|
15
|
+
/// <see cref="RegistrationMethod.Interceptor"/> and
|
|
16
|
+
/// <see cref="RegistrationMethod.GlobalAcceptAll"/> -- map to
|
|
17
|
+
/// <see cref="SlotKey.None"/>. Interceptor caches are deliberately out of
|
|
18
|
+
/// scope for the slot grid (their machinery is separate); global accept-all
|
|
19
|
+
/// is structurally a multi-slot registration handled by dedicated bus
|
|
20
|
+
/// state.
|
|
21
|
+
/// </para>
|
|
22
|
+
/// <para>
|
|
23
|
+
/// The table is validated once at type-init: every value of
|
|
24
|
+
/// <see cref="RegistrationMethod"/> must have an entry, otherwise an
|
|
25
|
+
/// <see cref="InvalidOperationException"/> is thrown. This guarantees that
|
|
26
|
+
/// adding a new registration method without wiring its axis is a
|
|
27
|
+
/// load-time failure, not a silent dispatch hole.
|
|
28
|
+
/// </para>
|
|
29
|
+
/// </remarks>
|
|
30
|
+
internal static class RegistrationMethodAxes
|
|
31
|
+
{
|
|
32
|
+
private static readonly SlotKey[] Table = BuildAndValidateTable();
|
|
33
|
+
|
|
34
|
+
/// <summary>
|
|
35
|
+
/// Returns the <see cref="SlotKey"/> for the supplied registration
|
|
36
|
+
/// method. Returns <see cref="SlotKey.None"/> when the method is
|
|
37
|
+
/// out-of-range or maps to the multi-slot / out-of-scope sentinel.
|
|
38
|
+
/// </summary>
|
|
39
|
+
/// <param name="method">The registration method to translate.</param>
|
|
40
|
+
/// <returns>
|
|
41
|
+
/// The mapped <see cref="SlotKey"/>, or <see cref="SlotKey.None"/> when
|
|
42
|
+
/// the method has no single-slot mapping.
|
|
43
|
+
/// </returns>
|
|
44
|
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
45
|
+
public static SlotKey GetSlotKey(RegistrationMethod method)
|
|
46
|
+
{
|
|
47
|
+
uint index = (uint)(int)method;
|
|
48
|
+
if (index >= (uint)Table.Length)
|
|
49
|
+
{
|
|
50
|
+
return SlotKey.None;
|
|
51
|
+
}
|
|
52
|
+
return Table[index];
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
private static SlotKey[] BuildAndValidateTable()
|
|
56
|
+
{
|
|
57
|
+
Array values = Enum.GetValues(typeof(RegistrationMethod));
|
|
58
|
+
int max = -1;
|
|
59
|
+
for (int i = 0; i < values.Length; i++)
|
|
60
|
+
{
|
|
61
|
+
int raw = (int)values.GetValue(i);
|
|
62
|
+
if (raw < 0)
|
|
63
|
+
{
|
|
64
|
+
throw new InvalidOperationException(
|
|
65
|
+
"RegistrationMethod enum contains a negative value: "
|
|
66
|
+
+ values.GetValue(i)
|
|
67
|
+
+ ". RegistrationMethodAxes assumes non-negative ordinals."
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
if (raw > max)
|
|
71
|
+
{
|
|
72
|
+
max = raw;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
SlotKey[] table = new SlotKey[max + 1];
|
|
77
|
+
for (int i = 0; i <= max; i++)
|
|
78
|
+
{
|
|
79
|
+
table[i] = SlotKey.None;
|
|
80
|
+
}
|
|
81
|
+
bool[] assigned = new bool[max + 1];
|
|
82
|
+
|
|
83
|
+
void Assign(RegistrationMethod method, SlotKey key)
|
|
84
|
+
{
|
|
85
|
+
int idx = (int)method;
|
|
86
|
+
if (assigned[idx])
|
|
87
|
+
{
|
|
88
|
+
throw new InvalidOperationException(
|
|
89
|
+
"RegistrationMethodAxes table assigned twice for "
|
|
90
|
+
+ method
|
|
91
|
+
+ ". Mapping must be unique."
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
table[idx] = key;
|
|
95
|
+
assigned[idx] = true;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Handle phase, default variant.
|
|
99
|
+
Assign(
|
|
100
|
+
RegistrationMethod.Targeted,
|
|
101
|
+
new SlotKey(DispatchKind.Targeted, DispatchPhase.Handle, DispatchVariant.Default)
|
|
102
|
+
);
|
|
103
|
+
Assign(
|
|
104
|
+
RegistrationMethod.Untargeted,
|
|
105
|
+
new SlotKey(DispatchKind.Untargeted, DispatchPhase.Handle, DispatchVariant.Default)
|
|
106
|
+
);
|
|
107
|
+
Assign(
|
|
108
|
+
RegistrationMethod.Broadcast,
|
|
109
|
+
new SlotKey(DispatchKind.Broadcast, DispatchPhase.Handle, DispatchVariant.Default)
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
// Handle phase, without-context variant.
|
|
113
|
+
Assign(
|
|
114
|
+
RegistrationMethod.BroadcastWithoutSource,
|
|
115
|
+
new SlotKey(
|
|
116
|
+
DispatchKind.Broadcast,
|
|
117
|
+
DispatchPhase.Handle,
|
|
118
|
+
DispatchVariant.WithoutContext
|
|
119
|
+
)
|
|
120
|
+
);
|
|
121
|
+
Assign(
|
|
122
|
+
RegistrationMethod.TargetedWithoutTargeting,
|
|
123
|
+
new SlotKey(
|
|
124
|
+
DispatchKind.Targeted,
|
|
125
|
+
DispatchPhase.Handle,
|
|
126
|
+
DispatchVariant.WithoutContext
|
|
127
|
+
)
|
|
128
|
+
);
|
|
129
|
+
|
|
130
|
+
// Sentinel mappings: multi-slot / out-of-scope.
|
|
131
|
+
Assign(RegistrationMethod.GlobalAcceptAll, SlotKey.None);
|
|
132
|
+
Assign(RegistrationMethod.Interceptor, SlotKey.None);
|
|
133
|
+
|
|
134
|
+
// Post-process phase, default variant.
|
|
135
|
+
Assign(
|
|
136
|
+
RegistrationMethod.UntargetedPostProcessor,
|
|
137
|
+
new SlotKey(
|
|
138
|
+
DispatchKind.Untargeted,
|
|
139
|
+
DispatchPhase.PostProcess,
|
|
140
|
+
DispatchVariant.Default
|
|
141
|
+
)
|
|
142
|
+
);
|
|
143
|
+
Assign(
|
|
144
|
+
RegistrationMethod.TargetedPostProcessor,
|
|
145
|
+
new SlotKey(
|
|
146
|
+
DispatchKind.Targeted,
|
|
147
|
+
DispatchPhase.PostProcess,
|
|
148
|
+
DispatchVariant.Default
|
|
149
|
+
)
|
|
150
|
+
);
|
|
151
|
+
Assign(
|
|
152
|
+
RegistrationMethod.BroadcastPostProcessor,
|
|
153
|
+
new SlotKey(
|
|
154
|
+
DispatchKind.Broadcast,
|
|
155
|
+
DispatchPhase.PostProcess,
|
|
156
|
+
DispatchVariant.Default
|
|
157
|
+
)
|
|
158
|
+
);
|
|
159
|
+
|
|
160
|
+
// Post-process phase, without-context variant.
|
|
161
|
+
Assign(
|
|
162
|
+
RegistrationMethod.TargetedWithoutTargetingPostProcessor,
|
|
163
|
+
new SlotKey(
|
|
164
|
+
DispatchKind.Targeted,
|
|
165
|
+
DispatchPhase.PostProcess,
|
|
166
|
+
DispatchVariant.WithoutContext
|
|
167
|
+
)
|
|
168
|
+
);
|
|
169
|
+
Assign(
|
|
170
|
+
RegistrationMethod.BroadcastWithoutSourcePostProcessor,
|
|
171
|
+
new SlotKey(
|
|
172
|
+
DispatchKind.Broadcast,
|
|
173
|
+
DispatchPhase.PostProcess,
|
|
174
|
+
DispatchVariant.WithoutContext
|
|
175
|
+
)
|
|
176
|
+
);
|
|
177
|
+
|
|
178
|
+
// Validate that every enum value received an explicit mapping.
|
|
179
|
+
for (int i = 0; i < values.Length; i++)
|
|
180
|
+
{
|
|
181
|
+
int raw = (int)values.GetValue(i);
|
|
182
|
+
if (!assigned[raw])
|
|
183
|
+
{
|
|
184
|
+
throw new InvalidOperationException(
|
|
185
|
+
"RegistrationMethodAxes is missing a mapping for "
|
|
186
|
+
+ (RegistrationMethod)raw
|
|
187
|
+
+ " (ordinal "
|
|
188
|
+
+ raw
|
|
189
|
+
+ "). Every RegistrationMethod must map to a SlotKey or SlotKey.None."
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// Tighten validation: walk every ordinal in [0..max]. Any unassigned
|
|
195
|
+
// index that does NOT correspond to a defined enum value is a gap
|
|
196
|
+
// (e.g. left behind by an [Obsolete]-removed member or sparse enum
|
|
197
|
+
// numbering) and would otherwise silently route into the Untargeted
|
|
198
|
+
// slot via default(SlotKey). SlotKey.None is the only safe sentinel
|
|
199
|
+
// for unmapped ordinals; gap ordinals must fail at type-init.
|
|
200
|
+
bool[] defined = new bool[max + 1];
|
|
201
|
+
for (int i = 0; i < values.Length; i++)
|
|
202
|
+
{
|
|
203
|
+
defined[(int)values.GetValue(i)] = true;
|
|
204
|
+
}
|
|
205
|
+
for (int i = 0; i <= max; i++)
|
|
206
|
+
{
|
|
207
|
+
if (!assigned[i] && !defined[i])
|
|
208
|
+
{
|
|
209
|
+
throw new InvalidOperationException(
|
|
210
|
+
"RegistrationMethodAxes ordinal "
|
|
211
|
+
+ i
|
|
212
|
+
+ " between defined values is unassigned. "
|
|
213
|
+
+ "Sparse RegistrationMethod ordinals are not supported; "
|
|
214
|
+
+ "every ordinal in [0..max] must map to a SlotKey or SlotKey.None."
|
|
215
|
+
);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
return table;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
namespace DxMessaging.Core.MessageBus.Internal
|
|
2
|
+
{
|
|
3
|
+
using System;
|
|
4
|
+
using System.Runtime.CompilerServices;
|
|
5
|
+
|
|
6
|
+
/// <summary>
|
|
7
|
+
/// Bit-packed coordinate that identifies a single dispatch slot along three
|
|
8
|
+
/// axes: <see cref="DispatchKind"/>, <see cref="DispatchPhase"/>, and
|
|
9
|
+
/// <see cref="DispatchVariant"/>. The byte-sized layout lets the bus index
|
|
10
|
+
/// into a small fixed-size array of slots without per-axis branching on the
|
|
11
|
+
/// hot dispatch path.
|
|
12
|
+
/// </summary>
|
|
13
|
+
/// <remarks>
|
|
14
|
+
/// <para>
|
|
15
|
+
/// Bit layout of <see cref="Packed"/>: <c>KKKK P VVV</c> where K is the
|
|
16
|
+
/// 4-bit <see cref="DispatchKind"/>, P is the 1-bit
|
|
17
|
+
/// <see cref="DispatchPhase"/>, and V is the 3-bit
|
|
18
|
+
/// <see cref="DispatchVariant"/>. The exact formula is
|
|
19
|
+
/// <c>packed = (kind << 4) | (phase << 3) | variant</c>.
|
|
20
|
+
/// </para>
|
|
21
|
+
/// <para>
|
|
22
|
+
/// The sentinel value <see cref="None"/> uses <c>packed = 0xFF</c> and
|
|
23
|
+
/// represents "no axis applies" -- it is returned for registration methods
|
|
24
|
+
/// (such as <see cref="DxMessaging.Core.MessageBus.RegistrationMethod.Interceptor"/>
|
|
25
|
+
/// and <see cref="DxMessaging.Core.MessageBus.RegistrationMethod.GlobalAcceptAll"/>)
|
|
26
|
+
/// whose dispatch is multi-slot or otherwise outside the axis grid.
|
|
27
|
+
/// </para>
|
|
28
|
+
/// <para>
|
|
29
|
+
/// <c>default(SlotKey)</c> is bit-identical to
|
|
30
|
+
/// <c>new SlotKey(DispatchKind.Untargeted, DispatchPhase.Handle, DispatchVariant.Default)</c>.
|
|
31
|
+
/// This is intentional -- uninitialized <see cref="SlotKey"/> fields decode
|
|
32
|
+
/// to a real, valid slot. Use <see cref="None"/> (packed = 0xFF) as the
|
|
33
|
+
/// sentinel for "no slot applies"; never use <c>default(SlotKey)</c> as a
|
|
34
|
+
/// sentinel.
|
|
35
|
+
/// </para>
|
|
36
|
+
/// </remarks>
|
|
37
|
+
internal readonly struct SlotKey : IEquatable<SlotKey>
|
|
38
|
+
{
|
|
39
|
+
private const int KindShift = 4;
|
|
40
|
+
private const int PhaseShift = 3;
|
|
41
|
+
private const byte KindMask = 0x0F;
|
|
42
|
+
private const byte PhaseMask = 0x01;
|
|
43
|
+
private const byte VariantMask = 0x07;
|
|
44
|
+
|
|
45
|
+
private const byte NonePacked = 0xFF;
|
|
46
|
+
|
|
47
|
+
/// <summary>
|
|
48
|
+
/// Sentinel slot key that represents "no axis applies". Distinct from
|
|
49
|
+
/// <c>default(SlotKey)</c>; equality with <c>default</c> is false.
|
|
50
|
+
/// </summary>
|
|
51
|
+
/// <remarks>
|
|
52
|
+
/// 0xFF is unreachable from the public ctor by construction; the ctor explicitly rejects the (15, 1, 7) triple.
|
|
53
|
+
/// </remarks>
|
|
54
|
+
public static readonly SlotKey None = new SlotKey(unpacked: NonePacked);
|
|
55
|
+
|
|
56
|
+
/// <summary>
|
|
57
|
+
/// The packed byte representation. Layout is
|
|
58
|
+
/// <c>(kind << 4) | (phase << 3) | variant</c>; the sentinel
|
|
59
|
+
/// <see cref="None"/> uses <c>0xFF</c>.
|
|
60
|
+
/// </summary>
|
|
61
|
+
public readonly byte Packed;
|
|
62
|
+
|
|
63
|
+
/// <summary>
|
|
64
|
+
/// Constructs a slot key from its three component axes.
|
|
65
|
+
/// </summary>
|
|
66
|
+
/// <param name="kind">Dispatch kind. Must fit in 4 bits (0..15).</param>
|
|
67
|
+
/// <param name="phase">Dispatch phase. Must fit in 1 bit (0..1).</param>
|
|
68
|
+
/// <param name="variant">Dispatch variant. Must fit in 3 bits (0..7).</param>
|
|
69
|
+
/// <exception cref="ArgumentOutOfRangeException">
|
|
70
|
+
/// Thrown when any axis exceeds the bits allotted for it.
|
|
71
|
+
/// </exception>
|
|
72
|
+
/// <exception cref="ArgumentException">
|
|
73
|
+
/// Thrown when the <c>(kind, phase, variant)</c> triple packs to the
|
|
74
|
+
/// reserved <see cref="None"/> sentinel bit pattern (<c>0xFF</c>),
|
|
75
|
+
/// i.e. <c>(15, 1, 7)</c>.
|
|
76
|
+
/// </exception>
|
|
77
|
+
public SlotKey(DispatchKind kind, DispatchPhase phase, DispatchVariant variant)
|
|
78
|
+
{
|
|
79
|
+
byte k = (byte)kind;
|
|
80
|
+
byte p = (byte)phase;
|
|
81
|
+
byte v = (byte)variant;
|
|
82
|
+
if (k > KindMask)
|
|
83
|
+
{
|
|
84
|
+
throw new ArgumentOutOfRangeException(
|
|
85
|
+
nameof(kind),
|
|
86
|
+
k,
|
|
87
|
+
"DispatchKind must fit in 4 bits (0..15)."
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
if (p > PhaseMask)
|
|
91
|
+
{
|
|
92
|
+
throw new ArgumentOutOfRangeException(
|
|
93
|
+
nameof(phase),
|
|
94
|
+
p,
|
|
95
|
+
"DispatchPhase must fit in 1 bit (0..1)."
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
if (v > VariantMask)
|
|
99
|
+
{
|
|
100
|
+
throw new ArgumentOutOfRangeException(
|
|
101
|
+
nameof(variant),
|
|
102
|
+
v,
|
|
103
|
+
"DispatchVariant must fit in 3 bits (0..7)."
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
byte packed = (byte)((k << KindShift) | (p << PhaseShift) | v);
|
|
107
|
+
if (packed == NonePacked)
|
|
108
|
+
{
|
|
109
|
+
throw new ArgumentException(
|
|
110
|
+
"(kind, phase, variant) triple packs to the SlotKey.None sentinel. "
|
|
111
|
+
+ "The bit pattern 0xFF is reserved for SlotKey.None and cannot be "
|
|
112
|
+
+ "constructed via the public ctor, i.e. (kind=15, phase=1, variant=7).",
|
|
113
|
+
nameof(variant)
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
Packed = packed;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
private SlotKey(byte unpacked)
|
|
120
|
+
{
|
|
121
|
+
Packed = unpacked;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/// <summary>The decoded <see cref="DispatchKind"/> axis.</summary>
|
|
125
|
+
public DispatchKind Kind
|
|
126
|
+
{
|
|
127
|
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
128
|
+
get => (DispatchKind)((Packed >> KindShift) & KindMask);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/// <summary>The decoded <see cref="DispatchPhase"/> axis.</summary>
|
|
132
|
+
public DispatchPhase Phase
|
|
133
|
+
{
|
|
134
|
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
135
|
+
get => (DispatchPhase)((Packed >> PhaseShift) & PhaseMask);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/// <summary>The decoded <see cref="DispatchVariant"/> axis.</summary>
|
|
139
|
+
public DispatchVariant Variant
|
|
140
|
+
{
|
|
141
|
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
142
|
+
get => (DispatchVariant)(Packed & VariantMask);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/// <inheritdoc />
|
|
146
|
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
147
|
+
public bool Equals(SlotKey other)
|
|
148
|
+
{
|
|
149
|
+
return Packed == other.Packed;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/// <inheritdoc />
|
|
153
|
+
public override bool Equals(object obj)
|
|
154
|
+
{
|
|
155
|
+
return obj is SlotKey other && Equals(other);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/// <inheritdoc />
|
|
159
|
+
public override int GetHashCode()
|
|
160
|
+
{
|
|
161
|
+
return Packed;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/// <summary>Equality operator. Compares the packed byte value.</summary>
|
|
165
|
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
166
|
+
public static bool operator ==(SlotKey left, SlotKey right)
|
|
167
|
+
{
|
|
168
|
+
return left.Packed == right.Packed;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/// <summary>Inequality operator. Compares the packed byte value.</summary>
|
|
172
|
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
173
|
+
public static bool operator !=(SlotKey left, SlotKey right)
|
|
174
|
+
{
|
|
175
|
+
return left.Packed != right.Packed;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/// <summary>
|
|
179
|
+
/// Returns "None" for the <see cref="None"/> sentinel; otherwise
|
|
180
|
+
/// returns a slash-delimited triple of the form
|
|
181
|
+
/// <c>"{Kind}/{Phase}/{Variant}"</c>.
|
|
182
|
+
/// </summary>
|
|
183
|
+
public override string ToString()
|
|
184
|
+
{
|
|
185
|
+
if (Packed == NonePacked)
|
|
186
|
+
{
|
|
187
|
+
return "None";
|
|
188
|
+
}
|
|
189
|
+
return Kind + "/" + Phase + "/" + Variant;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|