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