com.wallstop-studios.dxmessaging 2.1.9 → 3.0.1

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.
Files changed (249) hide show
  1. package/CHANGELOG.md +106 -65
  2. package/CHANGELOG.md.meta +7 -7
  3. package/Editor/Analyzers/BaseCallIlInspector.cs +277 -0
  4. package/Editor/Analyzers/BaseCallIlInspector.cs.meta +11 -0
  5. package/Editor/Analyzers/BaseCallLogMessageParser.cs +295 -0
  6. package/Editor/Analyzers/BaseCallLogMessageParser.cs.meta +11 -0
  7. package/Editor/Analyzers/BaseCallReportAggregator.cs +308 -0
  8. package/Editor/Analyzers/BaseCallReportAggregator.cs.meta +11 -0
  9. package/Editor/Analyzers/BaseCallTypeScanner.cs +110 -0
  10. package/Editor/Analyzers/BaseCallTypeScanner.cs.meta +11 -0
  11. package/Editor/Analyzers/BaseCallTypeScannerCore.cs +562 -0
  12. package/Editor/Analyzers/BaseCallTypeScannerCore.cs.meta +11 -0
  13. package/Editor/Analyzers/DxMessagingConsoleHarvester.cs +1122 -0
  14. package/Editor/Analyzers/DxMessagingConsoleHarvester.cs.meta +11 -0
  15. package/Editor/Analyzers/Microsoft.CodeAnalysis.CSharp.dll.meta +44 -44
  16. package/Editor/Analyzers/Microsoft.CodeAnalysis.dll.meta +44 -44
  17. package/Editor/Analyzers/System.Collections.Immutable.dll.meta +44 -44
  18. package/Editor/Analyzers/System.Reflection.Metadata.dll.meta +44 -44
  19. package/Editor/Analyzers/System.Runtime.CompilerServices.Unsafe.dll.meta +44 -44
  20. package/Editor/Analyzers/WallstopStudios.DxMessaging.Analyzer.dll +0 -0
  21. package/Editor/Analyzers/WallstopStudios.DxMessaging.Analyzer.dll.meta +33 -0
  22. package/Editor/Analyzers/WallstopStudios.DxMessaging.SourceGenerators.dll +0 -0
  23. package/Editor/Analyzers/WallstopStudios.DxMessaging.SourceGenerators.dll.meta +72 -72
  24. package/Editor/Analyzers.meta +8 -8
  25. package/Editor/AssemblyInfo.cs.meta +3 -3
  26. package/Editor/CustomEditors/MessageAwareComponentFallbackEditor.cs +81 -0
  27. package/Editor/CustomEditors/MessageAwareComponentFallbackEditor.cs.meta +11 -0
  28. package/Editor/CustomEditors/MessageAwareComponentInspectorOverlay.cs +420 -0
  29. package/Editor/CustomEditors/MessageAwareComponentInspectorOverlay.cs.meta +11 -0
  30. package/Editor/CustomEditors/MessagingComponentEditor.cs +1 -1
  31. package/Editor/CustomEditors/MessagingComponentEditor.cs.meta +2 -2
  32. package/Editor/CustomEditors.meta +2 -2
  33. package/Editor/DxMessagingEditorInitializer.cs +1 -1
  34. package/Editor/DxMessagingEditorInitializer.cs.meta +2 -2
  35. package/Editor/DxMessagingMenu.cs.meta +11 -11
  36. package/Editor/DxMessagingSceneBuildProcessor.cs.meta +11 -11
  37. package/Editor/Settings/DxMessagingBaseCallIgnoreSync.cs +190 -0
  38. package/Editor/Settings/DxMessagingBaseCallIgnoreSync.cs.meta +11 -0
  39. package/Editor/Settings/DxMessagingSettings.cs +189 -0
  40. package/Editor/Settings/DxMessagingSettings.cs.meta +2 -2
  41. package/Editor/Settings/DxMessagingSettingsProvider.cs +50 -33
  42. package/Editor/Settings/DxMessagingSettingsProvider.cs.meta +2 -2
  43. package/Editor/Settings.meta +2 -2
  44. package/Editor/SetupCscRsp.cs +209 -8
  45. package/Editor/SetupCscRsp.cs.meta +2 -2
  46. package/Editor/Testing/MessagingComponentEditorHarness.cs +1 -1
  47. package/Editor/Testing/MessagingComponentEditorHarness.cs.meta +3 -3
  48. package/Editor/Testing.meta +3 -3
  49. package/Editor/WallstopStudios.DxMessaging.Editor.asmdef +14 -14
  50. package/Editor/WallstopStudios.DxMessaging.Editor.asmdef.meta +7 -7
  51. package/Editor.meta +8 -8
  52. package/LICENSE.md +9 -9
  53. package/LICENSE.md.meta +7 -7
  54. package/README.md +941 -900
  55. package/README.md.meta +7 -7
  56. package/Runtime/AssemblyInfo.cs +4 -0
  57. package/Runtime/AssemblyInfo.cs.meta +2 -2
  58. package/Runtime/Core/Attributes/DxAutoConstructorAttribute.cs.meta +2 -2
  59. package/Runtime/Core/Attributes/DxBroadcastMessageAttribute.cs.meta +2 -2
  60. package/Runtime/Core/Attributes/DxIgnoreMissingBaseCallAttribute.cs +26 -0
  61. package/Runtime/Core/Attributes/DxIgnoreMissingBaseCallAttribute.cs.meta +11 -0
  62. package/Runtime/Core/Attributes/DxOptionalParameterAttribute.cs.meta +2 -2
  63. package/Runtime/Core/Attributes/DxTargetedMessageAttribute.cs.meta +2 -2
  64. package/Runtime/Core/Attributes/DxUntargetedMessageAttribute.cs.meta +2 -2
  65. package/Runtime/Core/Attributes.meta +2 -2
  66. package/Runtime/Core/Configuration/DxMessagingRuntimeSettings.cs +195 -0
  67. package/Runtime/Core/Configuration/DxMessagingRuntimeSettings.cs.meta +11 -0
  68. package/Runtime/Core/Configuration/DxMessagingRuntimeSettingsProvider.cs +179 -0
  69. package/Runtime/Core/Configuration/DxMessagingRuntimeSettingsProvider.cs.meta +11 -0
  70. package/Runtime/Core/Configuration.meta +9 -0
  71. package/Runtime/Core/DataStructure/CyclicBuffer.cs +2 -2
  72. package/Runtime/Core/DataStructure/CyclicBuffer.cs.meta +2 -2
  73. package/Runtime/Core/DataStructure.meta +2 -2
  74. package/Runtime/Core/Diagnostics/MessageEmissionData.cs.meta +2 -2
  75. package/Runtime/Core/Diagnostics/MessageRegistrationData.cs.meta +2 -2
  76. package/Runtime/Core/Diagnostics/MessageRegistrationType.cs.meta +2 -2
  77. package/Runtime/Core/Diagnostics.meta +2 -2
  78. package/Runtime/Core/DxMessagingStaticState.cs +19 -0
  79. package/Runtime/Core/DxMessagingStaticState.cs.meta +11 -11
  80. package/Runtime/Core/Extensions/EnumExtensions.cs.meta +2 -2
  81. package/Runtime/Core/Extensions/IListExtensions.cs.meta +2 -2
  82. package/Runtime/Core/Extensions/MessageBusExtensions.cs.meta +12 -12
  83. package/Runtime/Core/Extensions/MessageExtensions.cs.meta +11 -11
  84. package/Runtime/Core/Extensions.meta +8 -8
  85. package/Runtime/Core/Helper/MessageCache.cs +32 -0
  86. package/Runtime/Core/Helper/MessageCache.cs.meta +2 -2
  87. package/Runtime/Core/Helper/MessageHelperIndexer.cs.meta +2 -2
  88. package/Runtime/Core/Helper.meta +2 -2
  89. package/Runtime/Core/IMessage.cs +3 -3
  90. package/Runtime/Core/IMessage.cs.meta +11 -11
  91. package/Runtime/Core/InstanceId.cs.meta +11 -11
  92. package/Runtime/Core/Internal/TypedDispatchLinkIndex.cs +51 -0
  93. package/Runtime/Core/Internal/TypedDispatchLinkIndex.cs.meta +11 -0
  94. package/Runtime/Core/Internal/TypedGlobalSlotIndex.cs +38 -0
  95. package/Runtime/Core/Internal/TypedGlobalSlotIndex.cs.meta +11 -0
  96. package/Runtime/Core/Internal/TypedSlotIndex.cs +81 -0
  97. package/Runtime/Core/Internal/TypedSlotIndex.cs.meta +11 -0
  98. package/Runtime/Core/Internal/TypedSlots.cs +613 -0
  99. package/Runtime/Core/Internal/TypedSlots.cs.meta +11 -0
  100. package/Runtime/Core/Internal.meta +9 -0
  101. package/Runtime/Core/MessageBus/DiagnosticsTarget.cs.meta +11 -11
  102. package/Runtime/Core/MessageBus/GlobalMessageBusProvider.cs.meta +11 -11
  103. package/Runtime/Core/MessageBus/IMessageBus.cs +177 -3
  104. package/Runtime/Core/MessageBus/IMessageBus.cs.meta +11 -11
  105. package/Runtime/Core/MessageBus/IMessageBusProvider.cs.meta +11 -11
  106. package/Runtime/Core/MessageBus/IMessageRegistrationBuilder.cs.meta +11 -11
  107. package/Runtime/Core/MessageBus/Internal/BusContextIndex.cs +16 -0
  108. package/Runtime/Core/MessageBus/Internal/BusContextIndex.cs.meta +11 -0
  109. package/Runtime/Core/MessageBus/Internal/BusSinkIndex.cs +40 -0
  110. package/Runtime/Core/MessageBus/Internal/BusSinkIndex.cs.meta +11 -0
  111. package/Runtime/Core/MessageBus/Internal/BusSlots.cs +718 -0
  112. package/Runtime/Core/MessageBus/Internal/BusSlots.cs.meta +11 -0
  113. package/Runtime/Core/MessageBus/Internal/DispatchKind.cs +38 -0
  114. package/Runtime/Core/MessageBus/Internal/DispatchKind.cs.meta +11 -0
  115. package/Runtime/Core/MessageBus/Internal/DispatchPhase.cs +20 -0
  116. package/Runtime/Core/MessageBus/Internal/DispatchPhase.cs.meta +11 -0
  117. package/Runtime/Core/MessageBus/Internal/DispatchVariant.cs +28 -0
  118. package/Runtime/Core/MessageBus/Internal/DispatchVariant.cs.meta +11 -0
  119. package/Runtime/Core/MessageBus/Internal/IEvictableSlot.cs +48 -0
  120. package/Runtime/Core/MessageBus/Internal/IEvictableSlot.cs.meta +11 -0
  121. package/Runtime/Core/MessageBus/Internal/ISweepable.cs +15 -0
  122. package/Runtime/Core/MessageBus/Internal/ISweepable.cs.meta +11 -0
  123. package/Runtime/Core/MessageBus/Internal/RegistrationMethodAxes.cs +222 -0
  124. package/Runtime/Core/MessageBus/Internal/RegistrationMethodAxes.cs.meta +11 -0
  125. package/Runtime/Core/MessageBus/Internal/SlotKey.cs +192 -0
  126. package/Runtime/Core/MessageBus/Internal/SlotKey.cs.meta +11 -0
  127. package/Runtime/Core/MessageBus/Internal.meta +9 -0
  128. package/Runtime/Core/MessageBus/MessageBus.cs +2651 -500
  129. package/Runtime/Core/MessageBus/MessageBus.cs.meta +11 -11
  130. package/Runtime/Core/MessageBus/MessageBusRebindMode.cs.meta +11 -11
  131. package/Runtime/Core/MessageBus/MessageRegistrationBuilder.cs.meta +11 -11
  132. package/Runtime/Core/MessageBus/MessagingRegistration.cs.meta +11 -11
  133. package/Runtime/Core/MessageBus/RegistrationLog.cs.meta +11 -11
  134. package/Runtime/Core/MessageBus.meta +8 -8
  135. package/Runtime/Core/MessageHandler.cs +2019 -542
  136. package/Runtime/Core/MessageHandler.cs.meta +11 -11
  137. package/Runtime/Core/MessageRegistrationHandle.cs.meta +11 -11
  138. package/Runtime/Core/MessageRegistrationToken.cs +7 -0
  139. package/Runtime/Core/MessageRegistrationToken.cs.meta +11 -11
  140. package/Runtime/Core/Messages/GlobalStringMessage.cs.meta +2 -2
  141. package/Runtime/Core/Messages/IBroadcastMessage.cs.meta +11 -11
  142. package/Runtime/Core/Messages/ITargetedMessage.cs.meta +11 -11
  143. package/Runtime/Core/Messages/IUntargetedMessage.cs.meta +11 -11
  144. package/Runtime/Core/Messages/ReflexiveMessage.cs.meta +2 -2
  145. package/Runtime/Core/Messages/SourcedStringMessage.cs.meta +11 -11
  146. package/Runtime/Core/Messages/StringMessage.cs.meta +2 -2
  147. package/Runtime/Core/Messages.meta +8 -8
  148. package/Runtime/Core/MessagingDebug.cs.meta +11 -11
  149. package/Runtime/Core/Pooling/CollectionPool.cs +266 -0
  150. package/Runtime/Core/Pooling/CollectionPool.cs.meta +11 -0
  151. package/Runtime/Core/Pooling/CollectionPoolDiagnostics.cs +30 -0
  152. package/Runtime/Core/Pooling/CollectionPoolDiagnostics.cs.meta +11 -0
  153. package/Runtime/Core/Pooling/DxPools.cs +157 -0
  154. package/Runtime/Core/Pooling/DxPools.cs.meta +11 -0
  155. package/Runtime/Core/Pooling/EvictionPlayerLoopHook.cs +106 -0
  156. package/Runtime/Core/Pooling/EvictionPlayerLoopHook.cs.meta +11 -0
  157. package/Runtime/Core/Pooling/IDxMessagingClock.cs +18 -0
  158. package/Runtime/Core/Pooling/IDxMessagingClock.cs.meta +11 -0
  159. package/Runtime/Core/Pooling/PoolDiagnosticsSnapshot.cs +55 -0
  160. package/Runtime/Core/Pooling/PoolDiagnosticsSnapshot.cs.meta +11 -0
  161. package/Runtime/Core/Pooling/StopwatchClock.cs +27 -0
  162. package/Runtime/Core/Pooling/StopwatchClock.cs.meta +11 -0
  163. package/Runtime/Core/Pooling/UnityRealtimeClock.cs +31 -0
  164. package/Runtime/Core/Pooling/UnityRealtimeClock.cs.meta +11 -0
  165. package/Runtime/Core/Pooling.meta +9 -0
  166. package/Runtime/Core.meta +8 -8
  167. package/Runtime/Unity/CurrentGlobalMessageBusProvider.cs.meta +12 -12
  168. package/Runtime/Unity/DxMessagingRuntimeInitializer.cs.meta +11 -11
  169. package/Runtime/Unity/InitialGlobalMessageBusProvider.cs.meta +12 -12
  170. package/Runtime/Unity/Integrations/Reflex/AssemblyInfo.cs.meta +2 -2
  171. package/Runtime/Unity/Integrations/Reflex/ReflexRegistrationInstaller.cs +73 -0
  172. package/Runtime/Unity/Integrations/Reflex/ReflexRegistrationInstaller.cs.meta +11 -11
  173. package/Runtime/Unity/Integrations/Reflex/WallstopStudios.DxMessaging.Reflex.asmdef +20 -20
  174. package/Runtime/Unity/Integrations/Reflex/WallstopStudios.DxMessaging.Reflex.asmdef.meta +7 -7
  175. package/Runtime/Unity/Integrations/Reflex.meta +8 -8
  176. package/Runtime/Unity/Integrations/VContainer/AssemblyInfo.cs.meta +2 -2
  177. package/Runtime/Unity/Integrations/VContainer/VContainerRegistrationExtensions.cs +109 -1
  178. package/Runtime/Unity/Integrations/VContainer/VContainerRegistrationExtensions.cs.meta +11 -11
  179. package/Runtime/Unity/Integrations/VContainer/WallstopStudios.DxMessaging.VContainer.asmdef +30 -30
  180. package/Runtime/Unity/Integrations/VContainer/WallstopStudios.DxMessaging.VContainer.asmdef.meta +7 -7
  181. package/Runtime/Unity/Integrations/VContainer.meta +8 -8
  182. package/Runtime/Unity/Integrations/Zenject/AssemblyInfo.cs.meta +2 -2
  183. package/Runtime/Unity/Integrations/Zenject/WallstopStudios.DxMessaging.Zenject.asmdef +30 -30
  184. package/Runtime/Unity/Integrations/Zenject/WallstopStudios.DxMessaging.Zenject.asmdef.meta +7 -7
  185. package/Runtime/Unity/Integrations/Zenject/ZenjectRegistrationInstaller.cs +79 -1
  186. package/Runtime/Unity/Integrations/Zenject/ZenjectRegistrationInstaller.cs.meta +11 -11
  187. package/Runtime/Unity/Integrations/Zenject.meta +8 -8
  188. package/Runtime/Unity/Integrations.meta +8 -8
  189. package/Runtime/Unity/MessageAwareComponent.cs +29 -0
  190. package/Runtime/Unity/MessageAwareComponent.cs.meta +11 -11
  191. package/Runtime/Unity/MessageBusProviderHandle.cs.meta +12 -12
  192. package/Runtime/Unity/MessagingComponent.cs.meta +11 -11
  193. package/Runtime/Unity/MessagingComponentInstaller.cs.meta +12 -12
  194. package/Runtime/Unity/ScriptableMessageBusProvider.cs.meta +12 -12
  195. package/Runtime/Unity.meta +8 -8
  196. package/Runtime/WallstopStudios.DxMessaging.asmdef +14 -14
  197. package/Runtime/WallstopStudios.DxMessaging.asmdef.meta +7 -7
  198. package/Runtime.meta +8 -8
  199. package/Samples~/DI/Prefabs/MessagingInstallerSample.prefab +98 -98
  200. package/Samples~/DI/Prefabs/MessagingInstallerSample.prefab.meta +7 -7
  201. package/Samples~/DI/Prefabs.meta +8 -8
  202. package/Samples~/DI/Providers/GlobalMessageBusProvider.asset +14 -14
  203. package/Samples~/DI/Providers/GlobalMessageBusProvider.asset.meta +8 -8
  204. package/Samples~/DI/Providers/InitialGlobalMessageBusProvider.asset +14 -14
  205. package/Samples~/DI/Providers/InitialGlobalMessageBusProvider.asset.meta +8 -8
  206. package/Samples~/DI/Providers.meta +8 -8
  207. package/Samples~/DI/README.md +51 -51
  208. package/Samples~/DI/README.md.meta +7 -7
  209. package/Samples~/DI/Reflex/SampleInstaller.cs +7 -0
  210. package/Samples~/DI/Reflex/SampleInstaller.cs.meta +11 -11
  211. package/Samples~/DI/Reflex.meta +8 -8
  212. package/Samples~/DI/VContainer/SampleLifetimeScope.cs +6 -1
  213. package/Samples~/DI/VContainer/SampleLifetimeScope.cs.meta +11 -11
  214. package/Samples~/DI/VContainer.meta +8 -8
  215. package/Samples~/DI/Zenject/SampleInstaller.cs +8 -0
  216. package/Samples~/DI/Zenject/SampleInstaller.cs.meta +11 -11
  217. package/Samples~/DI/Zenject.meta +8 -8
  218. package/Samples~/DI.meta +8 -8
  219. package/Samples~/Mini Combat/Boot.cs.meta +11 -11
  220. package/Samples~/Mini Combat/Enemy.cs.meta +11 -11
  221. package/Samples~/Mini Combat/Messages.cs.meta +11 -11
  222. package/Samples~/Mini Combat/Player.cs.meta +11 -11
  223. package/Samples~/Mini Combat/README.md +324 -323
  224. package/Samples~/Mini Combat/README.md.meta +7 -7
  225. package/Samples~/Mini Combat/UIOverlay.cs.meta +11 -11
  226. package/Samples~/Mini Combat/Walkthrough.md +430 -430
  227. package/Samples~/Mini Combat/Walkthrough.md.meta +7 -7
  228. package/Samples~/Mini Combat/WallstopStudios.DxMessaging.MiniCombat.Sample.asmdef +13 -13
  229. package/Samples~/Mini Combat/WallstopStudios.DxMessaging.MiniCombat.Sample.asmdef.meta +7 -7
  230. package/Samples~/Mini Combat.meta +8 -8
  231. package/Samples~/UI Buttons + Inspector/DiagnosticsEnabler.cs.meta +11 -11
  232. package/Samples~/UI Buttons + Inspector/Messages.cs.meta +11 -11
  233. package/Samples~/UI Buttons + Inspector/MessagingObserver.cs.meta +11 -11
  234. package/Samples~/UI Buttons + Inspector/README.md +210 -209
  235. package/Samples~/UI Buttons + Inspector/README.md.meta +7 -7
  236. package/Samples~/UI Buttons + Inspector/UIButtonEmitter.cs.meta +11 -11
  237. package/Samples~/UI Buttons + Inspector/WallstopStudios.DxMessaging.UIButtons.Sample.asmdef +13 -13
  238. package/Samples~/UI Buttons + Inspector/WallstopStudios.DxMessaging.UIButtons.Sample.asmdef.meta +7 -7
  239. package/Samples~/UI Buttons + Inspector.meta +8 -8
  240. package/SourceGenerators/Directory.Build.props.meta +7 -7
  241. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/DxAutoConstructorGenerator.cs.meta +11 -11
  242. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/DxMessageIdGenerator.cs.meta +2 -2
  243. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators.csproj.meta +7 -7
  244. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators.meta +8 -8
  245. package/SourceGenerators.meta +8 -8
  246. package/Third Party Notices.md +3 -3
  247. package/Third Party Notices.md.meta +7 -7
  248. package/package.json +115 -92
  249. package/package.json.meta +7 -7
@@ -0,0 +1,613 @@
1
+ namespace DxMessaging.Core.Internal
2
+ {
3
+ using System.Collections.Generic;
4
+ using System.Runtime.CompilerServices;
5
+ using DxMessaging.Core;
6
+ using DxMessaging.Core.MessageBus.Internal;
7
+ using DxMessaging.Core.Pooling;
8
+
9
+ /// <summary>
10
+ /// Non-generic erasure interface over the per-delegate-shape
11
+ /// <c>HandlerActionCache&lt;TDelegate&gt;</c> type currently nested in
12
+ /// <see cref="MessageHandler"/>. Exposes only the metadata the staged
13
+ /// dispatch + eviction layers need so the typed-handler-side slot grid
14
+ /// (<see cref="TypedSlot{T}"/>, <see cref="TypedGlobalSlot"/>) can hold
15
+ /// caches polymorphically across the four typed delegate shapes
16
+ /// (<c>Action&lt;T&gt;</c>, <c>FastHandler&lt;T&gt;</c>,
17
+ /// <c>Action&lt;InstanceId, T&gt;</c>,
18
+ /// <c>FastHandlerWithContext&lt;T&gt;</c>) plus the six global
19
+ /// non-generic shapes (3 kinds {<c>IUntargetedMessage</c>,
20
+ /// <c>ITargetedMessage</c>, <c>IBroadcastMessage</c>} times 2 variants
21
+ /// {<c>Default</c>, <c>Fast</c>}), 10 distinct shapes total.
22
+ /// </summary>
23
+ /// <remarks>
24
+ /// <para>
25
+ /// <c>HandlerActionCache&lt;TDelegate&gt;</c> implements this interface
26
+ /// explicitly; the explicit form keeps the public field
27
+ /// shape on the nested cache type unchanged, so the public dispatch
28
+ /// surface picks up no new members from the interface retrofit.
29
+ /// </para>
30
+ /// <para>
31
+ /// Deliberately a thin, marker-style surface: only the six members that
32
+ /// staged dispatch (<see cref="Version"/>, <see cref="LastSeenVersion"/>,
33
+ /// <see cref="LastSeenEmissionId"/>,
34
+ /// <see cref="PrefreezeInvocationCount"/>) and eviction
35
+ /// (<see cref="IsEmpty"/>, <see cref="Reset"/>) require. The
36
+ /// <c>entries</c> dictionary and <c>cache</c> list are NOT exposed
37
+ /// because their generic shape is the very thing this interface erases;
38
+ /// dispatchers that need the typed cache down-cast at the call site.
39
+ /// </para>
40
+ /// </remarks>
41
+ internal interface IHandlerActionCache
42
+ {
43
+ /// <summary>
44
+ /// Strictly monotonic version counter for the cache's structural
45
+ /// state. Mirrors <c>HandlerActionCache&lt;TDelegate&gt;.version</c>.
46
+ /// Read-only on this surface; bumped internally by the cache's own
47
+ /// register / deregister sites and by <see cref="Reset"/>.
48
+ /// </summary>
49
+ long Version { get; }
50
+
51
+ /// <summary>
52
+ /// The <see cref="Version"/> value observed by the most recent
53
+ /// dispatcher snapshot. Mirrors
54
+ /// <c>HandlerActionCache&lt;TDelegate&gt;.lastSeenVersion</c> and is
55
+ /// mutated by the staged dispatch path to detect when the flat cache
56
+ /// list needs to be re-materialised.
57
+ /// </summary>
58
+ long LastSeenVersion { get; set; }
59
+
60
+ /// <summary>
61
+ /// The bus emission id of the most recent dispatch that consumed
62
+ /// this cache. Mirrors
63
+ /// <c>HandlerActionCache&lt;TDelegate&gt;.lastSeenEmissionId</c>.
64
+ /// Used by the staged dispatch staleness check. Implementations use
65
+ /// an invalid sentinel before the first dispatch so emission id 0
66
+ /// still materializes an initial snapshot.
67
+ /// </summary>
68
+ long LastSeenEmissionId { get; set; }
69
+
70
+ /// <summary>
71
+ /// Number of invocations observed during the prefreeze window for
72
+ /// the most recent dispatch. Mirrors
73
+ /// <c>HandlerActionCache&lt;TDelegate&gt;.prefreezeInvocationCount</c>.
74
+ /// Read-only on this surface; the cache's own dispatchers maintain
75
+ /// the value.
76
+ /// </summary>
77
+ int PrefreezeInvocationCount { get; }
78
+
79
+ /// <summary>
80
+ /// True iff the cache currently retains zero entries. Cheap (single
81
+ /// integer compare against <c>entries.Count</c>); used by the
82
+ /// eviction sweep so empty caches can be reclaimed without walking
83
+ /// inner state.
84
+ /// </summary>
85
+ bool IsEmpty { get; }
86
+
87
+ /// <summary>
88
+ /// Eviction-driven full clear. Empties the entries dictionary and
89
+ /// the flat cache list, resets <see cref="LastSeenVersion"/> /
90
+ /// <see cref="LastSeenEmissionId"/> / <c>prefreezeInvocationCount</c>,
91
+ /// and bumps <see cref="Version"/> as the LAST step so any captured
92
+ /// dispatch closure that observed the prior version detects
93
+ /// invalidation. Idempotent.
94
+ /// </summary>
95
+ void Reset();
96
+ }
97
+
98
+ /// <summary>
99
+ /// Non-generic sweep surface for <c>MessageHandler.TypedHandler&lt;T&gt;</c>.
100
+ /// The owning <see cref="MessageHandler"/> stores typed handlers in a
101
+ /// <c>MessageCache&lt;object&gt;</c>, so external reclamation code needs an
102
+ /// erased entry point that can reset empty typed slots without reflection.
103
+ /// </summary>
104
+ internal interface ITypedHandlerSlotSweeper
105
+ {
106
+ /// <summary>
107
+ /// Message type index for the owning typed-handler wrapper.
108
+ /// </summary>
109
+ int MessageTypeIndex { get; }
110
+
111
+ /// <summary>
112
+ /// True when the last sweep found no live typed slots or dispatch links
113
+ /// worth retaining and the owning <c>MessageCache</c> entry can be
114
+ /// removed.
115
+ /// </summary>
116
+ bool MarkedForOuterRemoval { get; }
117
+
118
+ /// <summary>
119
+ /// Resets every empty typed or typed-global slot and removes it from
120
+ /// the handler's slot arrays.
121
+ /// </summary>
122
+ /// <returns>Number of slots reset.</returns>
123
+ int ResetEmptySlotsForSweep();
124
+
125
+ /// <summary>
126
+ /// Resets every typed or typed-global slot and removes it from the
127
+ /// handler's slot arrays.
128
+ /// </summary>
129
+ /// <returns>Number of slots reset.</returns>
130
+ int ResetAllSlotsForBusReset();
131
+
132
+ /// <summary>
133
+ /// Counts empty typed or typed-global slots still occupying memory and
134
+ /// eligible for a sweep reset.
135
+ /// </summary>
136
+ /// <returns>Number of empty slots still allocated.</returns>
137
+ int CountEmptySlotsForSweep();
138
+ }
139
+
140
+ /// <summary>
141
+ /// Per-message-type, per-<see cref="SlotKey"/> dispatch slot on the
142
+ /// typed-handler side. Mirrors the role of
143
+ /// <see cref="BusSinkSlot"/> on the bus side: holds a priority-keyed map
144
+ /// of <see cref="IHandlerActionCache"/>s plus the snapshot-friendly
145
+ /// ordered-priority list, and tracks the staged-dispatch / eviction
146
+ /// counters.
147
+ /// </summary>
148
+ /// <remarks>
149
+ /// <para>
150
+ /// This type is sealed because the current slot layout uses one
151
+ /// type-erased cache shape for every delegate variant. A future
152
+ /// delegate-specific fast path can promote the type to <c>abstract</c>
153
+ /// together with its concrete subclasses, without affecting the current
154
+ /// storage contract.
155
+ /// </para>
156
+ /// <para>
157
+ /// The context requirement is represented as a readonly field
158
+ /// (<see cref="requiresContext"/>) set via the constructor. The field is
159
+ /// <c>true</c> for
160
+ /// slots whose <see cref="SlotKey"/> resolves to a
161
+ /// <see cref="DispatchVariant"/> that carries an
162
+ /// <see cref="InstanceId"/> recipient or source (Targeted / Broadcast,
163
+ /// excluding the <c>WithoutContext</c> variants), and <c>false</c>
164
+ /// otherwise.
165
+ /// </para>
166
+ /// <para>
167
+ /// <see cref="TypedHandler{T}"/> routes storage through this slot;
168
+ /// the legacy named fields were deleted and the
169
+ /// <c>_slots[<see cref="TypedSlotIndex.Length"/>]</c> array the
170
+ /// storage owner.
171
+ /// </para>
172
+ /// <para>
173
+ /// <see cref="TypedHandler{T}"/> owns a
174
+ /// <c>_dispatchLinks[<see cref="TypedDispatchLinkIndex.Length"/>]</c>
175
+ /// array as a plain <c>object[]</c> field. It is not a slot type; the
176
+ /// legacy named dispatch-link fields were removed.
177
+ /// </para>
178
+ /// </remarks>
179
+ /// <typeparam name="T">
180
+ /// The strongly-typed message contract this slot's parent
181
+ /// <see cref="TypedHandler{T}"/> binds to. The slot itself does not
182
+ /// reference <typeparamref name="T"/> directly today (the type-erased
183
+ /// <see cref="IHandlerActionCache"/> handles the per-delegate generic
184
+ /// shapes) -- the parameter is carried so typed storage can add a
185
+ /// concrete cache reference here without an additional
186
+ /// generic re-parameterization.
187
+ /// </typeparam>
188
+ internal sealed class TypedSlot<T> : IEvictableSlot
189
+ where T : IMessage
190
+ {
191
+ /// <summary>
192
+ /// Per-priority handler caches keyed by priority value.
193
+ /// <see cref="TypedHandler{T}"/> routes non-context storage through
194
+ /// this slot.
195
+ /// </summary>
196
+ public readonly Dictionary<int, IHandlerActionCache> byPriority = new();
197
+
198
+ /// <summary>
199
+ /// Insertion-ordered list of priority keys present in
200
+ /// <see cref="byPriority"/>. Mirrors the legacy ordered-priority
201
+ /// list used by the staged dispatch snapshot pattern.
202
+ /// </summary>
203
+ public readonly List<int> orderedPriorities = new();
204
+
205
+ /// <summary>Monotonic version counter for the slot's structural state.</summary>
206
+ public long version;
207
+
208
+ /// <summary>
209
+ /// The <see cref="version"/> value observed by the most recent
210
+ /// dispatcher snapshot. Used to decide whether the cache list needs
211
+ /// to be re-materialised before the next dispatch.
212
+ /// </summary>
213
+ public long lastSeenVersion = -1;
214
+
215
+ /// <summary>
216
+ /// The bus emission id of the most recent dispatch that consumed
217
+ /// this slot. Used by the staged dispatch staleness check.
218
+ /// </summary>
219
+ public long lastSeenEmissionId = -1;
220
+
221
+ /// <summary>
222
+ /// Bus tick counter value at the most recent register / deregister /
223
+ /// emit that touched this slot. Maintained by the sweep touch hook;
224
+ /// preserved across <see cref="Clear"/> and <see cref="Reset"/>
225
+ /// so the sweep can distinguish freshly-reset slots from
226
+ /// never-touched slots.
227
+ /// </summary>
228
+ public long lastTouchTicks;
229
+
230
+ /// <summary>
231
+ /// Reserved live-handler counter intended to mirror the unique
232
+ /// (handler, priority) pair count across every entry in
233
+ /// <see cref="byPriority"/>; for context-bound slots, the SUM of
234
+ /// (handler, priority) pair counts across every (InstanceId,
235
+ /// priority) leaf in <see cref="byContext"/> -- matching
236
+ /// <see cref="BusSinkSlot.liveCount"/> semantics so eviction logic
237
+ /// does not diverge between bus-side and handler-side.
238
+ /// <see cref="IsEmpty"/> is a single integer compare. The typed
239
+ /// handler maintains this counter on first-registration and
240
+ /// final-deregistration transitions so <see cref="IsEmpty"/>
241
+ /// reflects whether the slot still owns live handlers.
242
+ /// </summary>
243
+ public int liveCount;
244
+
245
+ /// <summary>
246
+ /// True iff this slot's <see cref="SlotKey"/> resolves to a
247
+ /// dispatch variant that carries an <see cref="InstanceId"/>
248
+ /// recipient or source (the non-<c>WithoutContext</c> Targeted and
249
+ /// Broadcast variants). When <c>true</c>, context-bound storage uses
250
+ /// <see cref="byContext"/>; when <c>false</c>, storage flows through
251
+ /// <see cref="byPriority"/> directly.
252
+ /// </summary>
253
+ /// <remarks>
254
+ /// Kept as a readonly field because <see cref="TypedSlot{T}"/> is
255
+ /// sealed (see class remarks).
256
+ /// </remarks>
257
+ public readonly bool requiresContext;
258
+
259
+ /// <summary>
260
+ /// Inner per-context map for context-bound slots. Null unless
261
+ /// <see cref="requiresContext"/> is <c>true</c> AND at least one
262
+ /// context has been registered.
263
+ /// </summary>
264
+ /// <remarks>
265
+ /// <para>
266
+ /// Lifetime semantic: <see cref="Clear"/> and <see cref="Reset"/>
267
+ /// return the outer context dictionary and every inner priority
268
+ /// dictionary to <see cref="DxPools"/> before nulling the field.
269
+ /// </para>
270
+ /// <para>
271
+ /// Unlike the bus-side <see cref="BusContextSlot.byContext"/>, which
272
+ /// is rented from <c>DxPools.InstanceIdDicts</c> as a
273
+ /// <c>Dictionary&lt;InstanceId, object&gt;</c> (boxed
274
+ /// <see cref="BusSinkSlot"/>) for cross-message-type pool sharing,
275
+ /// the typed-handler-side equivalent here is a strongly-typed
276
+ /// <c>Dictionary&lt;InstanceId, Dictionary&lt;int, IHandlerActionCache&gt;&gt;</c>.
277
+ /// Both the outer context dictionary and the inner priority
278
+ /// dictionaries are rented from typed-handler-specific
279
+ /// <see cref="DxPools"/> pools.
280
+ /// </para>
281
+ /// <para>
282
+ /// Shape: <c>InstanceId -&gt; (priority -&gt; IHandlerActionCache)</c>,
283
+ /// with the leaf cache type-erased to <see cref="IHandlerActionCache"/>.
284
+ /// The inner dictionary is keyed by priority, matching the legacy
285
+ /// <c>Dictionary&lt;InstanceId, Dictionary&lt;int, HandlerActionCache&lt;TDelegate&gt;&gt;&gt;</c>
286
+ /// layout on <c>MessageHandler.TypedHandler&lt;T&gt;</c>. The flat
287
+ /// 3-level shape was chosen over the alternatives (extend
288
+ /// <see cref="IHandlerActionCache"/> with per-priority buckets, or
289
+ /// recurse with <c>Dictionary&lt;InstanceId, TypedSlot&lt;T&gt;&gt;</c>)
290
+ /// because it preserves the legacy storage layout exactly and keeps
291
+ /// call sites aligned with the existing shape. The monotonic-version
292
+ /// drain contract on
293
+ /// <see cref="Reset"/> requires every inner cache to be drained through
294
+ /// <see cref="IHandlerActionCache.Reset"/> before the outer
295
+ /// container is cleared.
296
+ /// </para>
297
+ /// </remarks>
298
+ public Dictionary<InstanceId, Dictionary<int, IHandlerActionCache>> byContext;
299
+
300
+ /// <summary>
301
+ /// Constructs a <see cref="TypedSlot{T}"/> with the supplied
302
+ /// context-binding flag. All other fields take their default
303
+ /// initial values.
304
+ /// </summary>
305
+ /// <param name="requiresContext">
306
+ /// Value for <see cref="TypedSlot{T}.requiresContext"/>; see that
307
+ /// field's remarks for the semantic.
308
+ /// </param>
309
+ public TypedSlot(bool requiresContext)
310
+ {
311
+ this.requiresContext = requiresContext;
312
+ }
313
+
314
+ /// <inheritdoc />
315
+ public long LastTouchTicks
316
+ {
317
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
318
+ get => lastTouchTicks;
319
+ }
320
+
321
+ /// <inheritdoc />
322
+ public bool IsEmpty
323
+ {
324
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
325
+ get => liveCount == 0;
326
+ }
327
+
328
+ /// <inheritdoc />
329
+ public long Version
330
+ {
331
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
332
+ get => version;
333
+ }
334
+
335
+ /// <summary>
336
+ /// Full-reset semantic. Empties <see cref="byPriority"/> and
337
+ /// <see cref="orderedPriorities"/>, nulls out
338
+ /// <see cref="byContext"/>, and resets the staged-dispatch
339
+ /// counters. Resets <see cref="version"/> to <c>0</c>; this is NOT
340
+ /// monotonic and is intended only for the typed-handler analog of
341
+ /// <c>MessageBus.ResetState()</c> if and when that code path is
342
+ /// wired up. Use <see cref="Reset"/> for sweep-driven slot
343
+ /// reclamation.
344
+ /// </summary>
345
+ /// <remarks>
346
+ /// <para>
347
+ /// Mirrors <see cref="BusSinkSlot.Clear"/>. <see cref="byContext"/>
348
+ /// returns <see cref="byContext"/> and its inner priority
349
+ /// dictionaries to <see cref="DxPools"/>.
350
+ /// </para>
351
+ /// <para>
352
+ /// Unlike <see cref="BusSinkSlot.Clear"/> which drains inner buckets,
353
+ /// this <see cref="Clear"/> drops references only -- <see cref="Clear"/>
354
+ /// is intended for the typed-handler analog of
355
+ /// <c>MessageBus.ResetState()</c> where the entire
356
+ /// <see cref="MessageHandler"/> graph is being torn down, so per-cache
357
+ /// drain would be redundant work. <see cref="Reset"/> (eviction-driven)
358
+ /// DOES drain inner caches via <see cref="IHandlerActionCache.Reset"/>
359
+ /// because outer-version invalidation alone is insufficient when the
360
+ /// slot is being re-used after sweep.
361
+ /// </para>
362
+ /// </remarks>
363
+ public void Clear()
364
+ {
365
+ byPriority.Clear();
366
+ orderedPriorities.Clear();
367
+ ReturnContextDictionaries();
368
+ byContext = null;
369
+ version = 0;
370
+ lastSeenVersion = -1;
371
+ lastSeenEmissionId = -1;
372
+ liveCount = 0;
373
+ }
374
+
375
+ /// <summary>
376
+ /// Eviction-driven reset. Drains every inner
377
+ /// <see cref="IHandlerActionCache"/> held by <see cref="byPriority"/>
378
+ /// and <see cref="byContext"/> through
379
+ /// <see cref="IHandlerActionCache.Reset"/> first, then clears the
380
+ /// outer containers, then bumps <see cref="version"/> as the LAST
381
+ /// step so any captured dispatch closure that observed the prior
382
+ /// version detects invalidation.
383
+ /// <see cref="lastTouchTicks"/> is intentionally preserved so the
384
+ /// sweep can distinguish freshly-reset slots from never-touched
385
+ /// ones.
386
+ /// </summary>
387
+ /// <remarks>
388
+ /// Drain order is load-bearing: inner caches must be reset (and their
389
+ /// own monotonic versions bumped)
390
+ /// BEFORE the outer container is cleared, so any captured dispatch
391
+ /// closure observing an inner cache detects invalidation regardless
392
+ /// of whether the outer reference is still reachable. The outer
393
+ /// <see cref="version"/> bump is the LAST statement in the method
394
+ /// for the same reason at the slot level.
395
+ /// </remarks>
396
+ public void Reset()
397
+ {
398
+ // Inline the structural-clear body of Clear(); do NOT call
399
+ // Clear() because that resets version=0 and would break the
400
+ // monotonic invariant the eviction layer depends on: stale
401
+ // deregister closures captured before reset must observe a
402
+ // strictly larger version after reset and skip their work.
403
+ // Per-cache drain BEFORE the structural clear: every
404
+ // IHandlerActionCache.Reset() bumps its own version internally,
405
+ // so closures captured against the inner cache also detect
406
+ // invalidation -- not just closures captured against the slot.
407
+ foreach (KeyValuePair<int, IHandlerActionCache> kv in byPriority)
408
+ {
409
+ kv.Value?.Reset();
410
+ }
411
+ if (byContext != null)
412
+ {
413
+ foreach (
414
+ KeyValuePair<InstanceId, Dictionary<int, IHandlerActionCache>> ctx in byContext
415
+ )
416
+ {
417
+ if (ctx.Value == null)
418
+ {
419
+ continue;
420
+ }
421
+ foreach (KeyValuePair<int, IHandlerActionCache> kv in ctx.Value)
422
+ {
423
+ kv.Value?.Reset();
424
+ }
425
+ }
426
+ }
427
+ byPriority.Clear();
428
+ orderedPriorities.Clear();
429
+ ReturnContextDictionaries();
430
+ byContext = null;
431
+ lastSeenVersion = -1;
432
+ lastSeenEmissionId = -1;
433
+ liveCount = 0;
434
+ unchecked
435
+ {
436
+ ++version;
437
+ }
438
+ }
439
+
440
+ private void ReturnContextDictionaries()
441
+ {
442
+ if (byContext == null)
443
+ {
444
+ return;
445
+ }
446
+
447
+ foreach (
448
+ KeyValuePair<InstanceId, Dictionary<int, IHandlerActionCache>> ctx in byContext
449
+ )
450
+ {
451
+ DxPools.TypedHandlerPriorityDicts.Return(ctx.Value);
452
+ }
453
+ DxPools.TypedHandlerContextDicts.Return(byContext);
454
+ }
455
+ }
456
+
457
+ /// <summary>
458
+ /// Per-message-type accept-all slot on the typed-handler side. Mirrors
459
+ /// the role of <see cref="BusGlobalSlot"/> on the bus side: holds a
460
+ /// single type-erased cache for the slot's
461
+ /// (<see cref="DispatchKind"/>, <see cref="DispatchVariant"/>)
462
+ /// coordinate and the staged-dispatch / eviction counters.
463
+ /// </summary>
464
+ /// <remarks>
465
+ /// <para>
466
+ /// The typed handler holds an array of 6 <see cref="TypedGlobalSlot"/>
467
+ /// entries. The per-(<see cref="DispatchKind"/>,
468
+ /// <see cref="DispatchVariant"/>) indexing scheme maps the six global
469
+ /// flavours (3 kinds {<c>Untargeted</c>, <c>Targeted</c>,
470
+ /// <c>Broadcast</c>} times 2 variants {<c>Default</c>, <c>Fast</c>}) to
471
+ /// array slots and is committed in <see cref="TypedGlobalSlotIndex"/>
472
+ /// (sibling file in the same folder). This type defines the per-slot
473
+ /// shape; the index file owns the layout decision.
474
+ /// <see cref="TypedHandler{T}"/> routes global storage through this type.
475
+ /// </para>
476
+ /// <para>
477
+ /// Non-generic by design: the typed handler's six legacy global
478
+ /// fields each carry a different non-generic delegate shape
479
+ /// (<c>Action&lt;IUntargetedMessage&gt;</c>,
480
+ /// <c>FastHandler&lt;IUntargetedMessage&gt;</c>,
481
+ /// <c>Action&lt;InstanceId, ITargetedMessage&gt;</c>, etc.), and the
482
+ /// bus-side <see cref="BusGlobalSlot"/> mirrors this. The single
483
+ /// <see cref="cache"/> field holds an erased
484
+ /// <see cref="IHandlerActionCache"/> whose concrete generic shape is
485
+ /// determined by the slot's coordinate; dispatchers down-cast at the
486
+ /// call site.
487
+ /// </para>
488
+ /// <para>
489
+ /// Single <see cref="cache"/> field intentionally -- not three like
490
+ /// <see cref="BusGlobalSlot"/>'s
491
+ /// <c>untargetedDispatchState</c> / <c>targetedDispatchState</c> /
492
+ /// <c>broadcastDispatchState</c> trio. The typed-handler-side global
493
+ /// array is the per-kind-and-variant fan-out (six slots), so each
494
+ /// slot already corresponds to a single kind+variant coordinate and
495
+ /// holds exactly one cache.
496
+ /// </para>
497
+ /// </remarks>
498
+ internal sealed class TypedGlobalSlot : IEvictableSlot
499
+ {
500
+ /// <summary>
501
+ /// Type-erased handler cache for this slot's
502
+ /// (<see cref="DispatchKind"/>, <see cref="DispatchVariant"/>)
503
+ /// coordinate. Lazy alloc on first registration; nulled by
504
+ /// <see cref="Clear"/> and <see cref="Reset"/>.
505
+ /// </summary>
506
+ public IHandlerActionCache cache;
507
+
508
+ /// <summary>Monotonic version counter for the slot's structural state.</summary>
509
+ public long version;
510
+
511
+ /// <summary>
512
+ /// The <see cref="version"/> value observed by the most recent
513
+ /// dispatcher snapshot.
514
+ /// </summary>
515
+ public long lastSeenVersion = -1;
516
+
517
+ /// <summary>
518
+ /// The bus emission id of the most recent dispatch that consumed
519
+ /// this slot.
520
+ /// </summary>
521
+ public long lastSeenEmissionId = -1;
522
+
523
+ /// <summary>
524
+ /// Bus tick counter value at the most recent register / deregister /
525
+ /// emit that touched this slot. Maintained by the sweep touch hook;
526
+ /// preserved across <see cref="Clear"/> and
527
+ /// <see cref="Reset"/>.
528
+ /// </summary>
529
+ public long lastTouchTicks;
530
+
531
+ /// <summary>
532
+ /// Reserved live-handler counter intended to mirror the entry count
533
+ /// of <see cref="cache"/> at every stable observation point so
534
+ /// <see cref="IsEmpty"/> is a single integer compare rather than a
535
+ /// dispatch through the type-erased
536
+ /// <see cref="IHandlerActionCache.IsEmpty"/> property. The typed
537
+ /// handler maintains this counter on first-registration and
538
+ /// final-deregistration transitions so <see cref="IsEmpty"/>
539
+ /// reflects whether the slot still owns live global handlers.
540
+ /// </summary>
541
+ public int liveCount;
542
+
543
+ /// <inheritdoc />
544
+ public long LastTouchTicks
545
+ {
546
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
547
+ get => lastTouchTicks;
548
+ }
549
+
550
+ /// <inheritdoc />
551
+ public bool IsEmpty
552
+ {
553
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
554
+ get => liveCount == 0;
555
+ }
556
+
557
+ /// <inheritdoc />
558
+ public long Version
559
+ {
560
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
561
+ get => version;
562
+ }
563
+
564
+ /// <summary>
565
+ /// Full-reset semantic. Nulls out <see cref="cache"/> and resets
566
+ /// the staged-dispatch counters. Resets <see cref="version"/> to
567
+ /// <c>0</c>; this is NOT monotonic and is intended only for the
568
+ /// typed-handler analog of <c>MessageBus.ResetState()</c> if and
569
+ /// when that code path is wired up. Use <see cref="Reset"/> for
570
+ /// sweep-driven slot reclamation.
571
+ /// </summary>
572
+ public void Clear()
573
+ {
574
+ cache = null;
575
+ version = 0;
576
+ lastSeenVersion = -1;
577
+ lastSeenEmissionId = -1;
578
+ liveCount = 0;
579
+ }
580
+
581
+ /// <summary>
582
+ /// Eviction-driven reset. Drains <see cref="cache"/> through
583
+ /// <see cref="IHandlerActionCache.Reset"/> first, then nulls the
584
+ /// reference, then bumps <see cref="version"/> as the LAST step so
585
+ /// any captured dispatch closure that observed the prior version
586
+ /// detects invalidation.
587
+ /// <see cref="lastTouchTicks"/> is intentionally preserved.
588
+ /// </summary>
589
+ /// <remarks>
590
+ /// Drain order is load-bearing: the inner cache's own monotonic
591
+ /// version is bumped BEFORE the slot
592
+ /// drops the reference, so closures captured against the inner
593
+ /// cache also detect invalidation. The outer <see cref="version"/>
594
+ /// bump is the LAST statement in the method for the same reason at
595
+ /// the slot level.
596
+ /// </remarks>
597
+ public void Reset()
598
+ {
599
+ // Inline the structural-clear body of Clear(); do NOT call
600
+ // Clear() because that resets version=0 and would break the
601
+ // monotonic invariant the eviction layer depends on.
602
+ cache?.Reset();
603
+ cache = null;
604
+ lastSeenVersion = -1;
605
+ lastSeenEmissionId = -1;
606
+ liveCount = 0;
607
+ unchecked
608
+ {
609
+ ++version;
610
+ }
611
+ }
612
+ }
613
+ }
@@ -0,0 +1,11 @@
1
+ fileFormatVersion: 2
2
+ guid: fbabf0ef529c40d6a613536b5a2e185e
3
+ MonoImporter:
4
+ externalObjects: {}
5
+ serializedVersion: 2
6
+ defaultReferences: []
7
+ executionOrder: 0
8
+ icon: {instanceID: 0}
9
+ userData:
10
+ assetBundleName:
11
+ assetBundleVariant:
@@ -0,0 +1,9 @@
1
+ fileFormatVersion: 2
2
+ guid: 705ffeb04a4b4d8fbbdbab114cbc560f
3
+ timeCreated: 1777840186
4
+ folderAsset: yes
5
+ DefaultImporter:
6
+ externalObjects: {}
7
+ userData:
8
+ assetBundleName:
9
+ assetBundleVariant:
@@ -1,11 +1,11 @@
1
- fileFormatVersion: 2
2
- guid: d2ff6bbe0b187ff4ab1051164b721d67
3
- MonoImporter:
4
- externalObjects: {}
5
- serializedVersion: 2
6
- defaultReferences: []
7
- executionOrder: 0
8
- icon: {instanceID: 0}
9
- userData:
10
- assetBundleName:
11
- assetBundleVariant:
1
+ fileFormatVersion: 2
2
+ guid: d2ff6bbe0b187ff4ab1051164b721d67
3
+ MonoImporter:
4
+ externalObjects: {}
5
+ serializedVersion: 2
6
+ defaultReferences: []
7
+ executionOrder: 0
8
+ icon: {instanceID: 0}
9
+ userData:
10
+ assetBundleName:
11
+ assetBundleVariant: