com.wallstop-studios.dxmessaging 3.2.0 → 3.2.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.
- package/CHANGELOG.md +40 -0
- package/Editor/Analyzers/DxMessagingConsoleHarvester.cs +8 -8
- package/Editor/CustomEditors/MessageAwareComponentFallbackEditor.cs +171 -13
- package/Editor/CustomEditors/MessageAwareComponentInspectorOverlay.cs +391 -96
- package/Editor/CustomEditors/MessageAwareComponentInspectorView.cs +279 -0
- package/Editor/CustomEditors/MessageAwareComponentInspectorView.cs.meta +11 -0
- package/Editor/DxMessagingEditorPalette.cs +66 -0
- package/Editor/DxMessagingEditorPalette.cs.meta +11 -0
- package/Editor/DxMessagingEditorTheme.cs +200 -0
- package/Editor/DxMessagingEditorTheme.cs.meta +11 -0
- package/Editor/Icons/dxmessaging-icon-256.png +0 -0
- package/Editor/Icons/dxmessaging-icon-256.png.meta +156 -0
- package/Editor/Icons/dxmessaging-icon-32.png +0 -0
- package/Editor/Icons/dxmessaging-icon-32.png.meta +156 -0
- package/Editor/Icons/dxmessaging-icon-48.png +0 -0
- package/Editor/Icons/dxmessaging-icon-48.png.meta +156 -0
- package/Editor/Icons.meta +8 -0
- package/Editor/Settings/DxMessagingSettingsProvider.cs +368 -33
- package/Editor/Testing/MessagingComponentEditorHarness.cs +11 -4
- package/Editor/Theme/DxMessagingTheme.uss +255 -0
- package/Editor/Theme/DxMessagingTheme.uss.meta +11 -0
- package/Editor/Theme/DxTokens.uss +90 -0
- package/Editor/Theme/DxTokens.uss.meta +11 -0
- package/Editor/Theme.meta +8 -0
- package/Editor/Windows/DxMessagingFlowGraphWindow.cs +5513 -0
- package/Editor/Windows/DxMessagingFlowGraphWindow.cs.meta +11 -0
- package/Editor/Windows/DxMessagingMessageMonitorWindow.cs +2288 -0
- package/Editor/Windows/DxMessagingMessageMonitorWindow.cs.meta +11 -0
- package/Editor/Windows.meta +8 -0
- package/README.md +84 -35
- package/Runtime/AssemblyInfo.cs +1 -0
- package/Runtime/Core/Diagnostics/MessageEmissionData.cs +29 -1
- package/Runtime/Core/Extensions/MessageExtensions.cs +4 -5
- package/Runtime/Core/Helper/MessageCache.cs +56 -23
- package/Runtime/Core/Internal/FlatDispatch.cs +32 -0
- package/Runtime/Core/Internal/TypedSlots.cs +3 -7
- package/Runtime/Core/MessageBus/MessageBus.cs +577 -142
- package/Runtime/Core/MessageBus/RegistrationLog.cs +25 -12
- package/Runtime/Core/MessageHandler.cs +774 -786
- package/Runtime/Core/MessageRegistrationHandle.cs +19 -5
- package/Runtime/Core/MessageRegistrationToken.cs +1080 -520
- package/Samples~/Diagnostics Tooling Exerciser/DiagnosticsToolingExerciser.cs +173 -0
- package/Samples~/Diagnostics Tooling Exerciser/DiagnosticsToolingExerciser.cs.meta +11 -0
- package/Samples~/Diagnostics Tooling Exerciser/DiagnosticsToolingExerciser.unity +424 -0
- package/Samples~/Diagnostics Tooling Exerciser/DiagnosticsToolingExerciser.unity.meta +7 -0
- package/Samples~/Diagnostics Tooling Exerciser/DiagnosticsToolingReceiver.cs +185 -0
- package/Samples~/Diagnostics Tooling Exerciser/DiagnosticsToolingReceiver.cs.meta +11 -0
- package/Samples~/Diagnostics Tooling Exerciser/Messages.cs +46 -0
- package/Samples~/Diagnostics Tooling Exerciser/Messages.cs.meta +11 -0
- package/Samples~/Diagnostics Tooling Exerciser/README.md +53 -0
- package/Samples~/Diagnostics Tooling Exerciser/README.md.meta +7 -0
- package/Samples~/Diagnostics Tooling Exerciser/WallstopStudios.DxMessaging.DiagnosticsToolingExerciser.Sample.asmdef +13 -0
- package/Samples~/Diagnostics Tooling Exerciser/WallstopStudios.DxMessaging.DiagnosticsToolingExerciser.Sample.asmdef.meta +7 -0
- package/Samples~/Diagnostics Tooling Exerciser.meta +8 -0
- package/Samples~/Mini Combat/README.md +1 -1
- package/Samples~/Mini Combat/Walkthrough.md +3 -3
- package/docs/images/DxMessaging-banner.svg +79 -0
- package/docs/images/DxMessaging-banner.svg.meta +53 -0
- package/docs/images.meta +8 -0
- package/docs.meta +8 -0
- package/package.json +13 -4
|
@@ -68,46 +68,35 @@ namespace DxMessaging.Core
|
|
|
68
68
|
// priority, and kind are now plain fields, and the diagnostics-augmented
|
|
69
69
|
// invoker is an instance method bound to the object (the FastHandler<T> handed
|
|
70
70
|
// to MessageHandler is (FastHandler<T>)registration.AugmentedHandlerScalar).
|
|
71
|
-
//
|
|
71
|
+
// The registration also owns its common teardown state, eliminating the separate
|
|
72
|
+
// HandlerDeregistration object; an allocation-backed wrapper is created only for
|
|
73
|
+
// overlapping retry/recovery state. Net ~ -3 managed allocations per registration.
|
|
74
|
+
// The central replay loop pairs
|
|
72
75
|
// the Registration with its handle and performs the AddDeregistration. The
|
|
73
76
|
// re-entrancy snapshot semantics are unchanged: the replay queue captures the
|
|
74
77
|
// Registration reference (exactly as it previously captured the staging Func),
|
|
75
78
|
// so a registration removed mid-replay is still replayed if it was already
|
|
76
79
|
// snapshotted.
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
//
|
|
80
|
-
//
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
private readonly Dictionary<MessageRegistrationHandle, object> _deregistrations = new();
|
|
98
|
-
|
|
99
|
-
// Snapshot of (handle, Registration object) pairs to replay on Enable() /
|
|
100
|
-
// RetargetMessageBus. Snapshotting before invoking lets replay tolerate
|
|
101
|
-
// re-entrant registration mutation (a handler that registers or removes
|
|
102
|
-
// handlers while it runs). The pair carries the handle so the central replay
|
|
103
|
-
// loop can call Registration.Register() and AddDeregistration without a
|
|
104
|
-
// per-registration wrapper closure.
|
|
105
|
-
private readonly List<StagedRegistration> _registrationReplayQueue = new();
|
|
106
|
-
private readonly List<MessageRegistrationHandle> _handleQueue = new();
|
|
107
|
-
internal readonly Dictionary<
|
|
108
|
-
MessageRegistrationHandle,
|
|
109
|
-
MessageRegistrationMetadata
|
|
110
|
-
> _metadata = new();
|
|
80
|
+
// Token-owned arena. A handle identifies a slot and the globally unique id that
|
|
81
|
+
// occupied it. Both are validated, so stale handles remain harmless after slot reuse.
|
|
82
|
+
// The doubly-linked live list preserves registration order while the singly-linked
|
|
83
|
+
// free list makes insertion and removal O(1).
|
|
84
|
+
private RegistrationSlot[] _slots = Array.Empty<RegistrationSlot>();
|
|
85
|
+
private int _registrationHead = -1;
|
|
86
|
+
private int _registrationTail = -1;
|
|
87
|
+
private int _freeSlotHead = -1;
|
|
88
|
+
private int _registrationCount;
|
|
89
|
+
private int _deregistrationCount;
|
|
90
|
+
|
|
91
|
+
// Lifecycle snapshots are exceptional-path storage and materialize only when a replay,
|
|
92
|
+
// teardown, or retarget actually needs them.
|
|
93
|
+
private List<StagedRegistration> _registrationReplayQueue;
|
|
94
|
+
private List<TeardownIdentity> _teardownQueue;
|
|
95
|
+
private Dictionary<MessageRegistrationHandle, int> _rollbackCounts;
|
|
96
|
+
private List<MessageRegistrationHandle> _activeRetargetHandles;
|
|
97
|
+
private Dictionary<MessageRegistrationHandle, object> _orphanDeregistrations;
|
|
98
|
+
|
|
99
|
+
internal RegistrationMetadataView _metadata => new RegistrationMetadataView(this);
|
|
111
100
|
|
|
112
101
|
// Diagnostics-only collections, allocated lazily on first use. A token whose
|
|
113
102
|
// owner never enables diagnostics (the default -- GlobalDiagnosticsTargets is
|
|
@@ -134,6 +123,22 @@ namespace DxMessaging.Core
|
|
|
134
123
|
IMessageBus.GlobalMessageBufferSize
|
|
135
124
|
);
|
|
136
125
|
|
|
126
|
+
internal void RecordDiagnosticEmission(
|
|
127
|
+
MessageRegistrationHandle handle,
|
|
128
|
+
IMessageBus messageBus,
|
|
129
|
+
IMessage message,
|
|
130
|
+
InstanceId? context = null
|
|
131
|
+
)
|
|
132
|
+
{
|
|
133
|
+
_callCounts[handle] = _callCounts.GetValueOrDefault(handle) + 1;
|
|
134
|
+
long traceId =
|
|
135
|
+
messageBus is DxMessaging.Core.MessageBus.MessageBus concreteBus
|
|
136
|
+
&& concreteBus.IsDispatching
|
|
137
|
+
? concreteBus.EmissionId
|
|
138
|
+
: 0;
|
|
139
|
+
_emissionBuffer.Add(new MessageEmissionData(message, context, traceId, handle));
|
|
140
|
+
}
|
|
141
|
+
|
|
137
142
|
private IMessageBus _messageBus;
|
|
138
143
|
private bool _enabled;
|
|
139
144
|
private bool _diagnosticMode = IMessageBus.ShouldEnableDiagnostics();
|
|
@@ -164,12 +169,6 @@ namespace DxMessaging.Core
|
|
|
164
169
|
target,
|
|
165
170
|
targetedHandler,
|
|
166
171
|
priority
|
|
167
|
-
),
|
|
168
|
-
new MessageRegistrationMetadata(
|
|
169
|
-
target,
|
|
170
|
-
typeof(T),
|
|
171
|
-
MessageRegistrationType.Targeted,
|
|
172
|
-
priority
|
|
173
172
|
)
|
|
174
173
|
);
|
|
175
174
|
}
|
|
@@ -193,12 +192,6 @@ namespace DxMessaging.Core
|
|
|
193
192
|
target,
|
|
194
193
|
targetedHandler,
|
|
195
194
|
priority
|
|
196
|
-
),
|
|
197
|
-
new MessageRegistrationMetadata(
|
|
198
|
-
target,
|
|
199
|
-
typeof(T),
|
|
200
|
-
MessageRegistrationType.Targeted,
|
|
201
|
-
priority
|
|
202
195
|
)
|
|
203
196
|
);
|
|
204
197
|
}
|
|
@@ -327,12 +320,6 @@ namespace DxMessaging.Core
|
|
|
327
320
|
target,
|
|
328
321
|
targetedPostProcessor,
|
|
329
322
|
priority
|
|
330
|
-
),
|
|
331
|
-
new MessageRegistrationMetadata(
|
|
332
|
-
target,
|
|
333
|
-
typeof(T),
|
|
334
|
-
MessageRegistrationType.TargetedPostProcessor,
|
|
335
|
-
priority
|
|
336
323
|
)
|
|
337
324
|
);
|
|
338
325
|
}
|
|
@@ -359,12 +346,6 @@ namespace DxMessaging.Core
|
|
|
359
346
|
target,
|
|
360
347
|
targetedPostProcessor,
|
|
361
348
|
priority
|
|
362
|
-
),
|
|
363
|
-
new MessageRegistrationMetadata(
|
|
364
|
-
target,
|
|
365
|
-
typeof(T),
|
|
366
|
-
MessageRegistrationType.TargetedPostProcessor,
|
|
367
|
-
priority
|
|
368
349
|
)
|
|
369
350
|
);
|
|
370
351
|
}
|
|
@@ -434,12 +415,6 @@ namespace DxMessaging.Core
|
|
|
434
415
|
target,
|
|
435
416
|
targetedPostProcessor,
|
|
436
417
|
priority
|
|
437
|
-
),
|
|
438
|
-
new MessageRegistrationMetadata(
|
|
439
|
-
target,
|
|
440
|
-
typeof(T),
|
|
441
|
-
MessageRegistrationType.TargetedPostProcessor,
|
|
442
|
-
priority
|
|
443
418
|
)
|
|
444
419
|
);
|
|
445
420
|
}
|
|
@@ -466,12 +441,6 @@ namespace DxMessaging.Core
|
|
|
466
441
|
target,
|
|
467
442
|
targetedPostProcessor,
|
|
468
443
|
priority
|
|
469
|
-
),
|
|
470
|
-
new MessageRegistrationMetadata(
|
|
471
|
-
target,
|
|
472
|
-
typeof(T),
|
|
473
|
-
MessageRegistrationType.TargetedPostProcessor,
|
|
474
|
-
priority
|
|
475
444
|
)
|
|
476
445
|
);
|
|
477
446
|
}
|
|
@@ -503,12 +472,6 @@ namespace DxMessaging.Core
|
|
|
503
472
|
default,
|
|
504
473
|
messageHandler,
|
|
505
474
|
priority
|
|
506
|
-
),
|
|
507
|
-
new MessageRegistrationMetadata(
|
|
508
|
-
null,
|
|
509
|
-
typeof(T),
|
|
510
|
-
MessageRegistrationType.TargetedWithoutTargeting,
|
|
511
|
-
priority
|
|
512
475
|
)
|
|
513
476
|
);
|
|
514
477
|
}
|
|
@@ -540,12 +503,6 @@ namespace DxMessaging.Core
|
|
|
540
503
|
default,
|
|
541
504
|
messageHandler,
|
|
542
505
|
priority
|
|
543
|
-
),
|
|
544
|
-
new MessageRegistrationMetadata(
|
|
545
|
-
null,
|
|
546
|
-
typeof(T),
|
|
547
|
-
MessageRegistrationType.TargetedWithoutTargeting,
|
|
548
|
-
priority
|
|
549
506
|
)
|
|
550
507
|
);
|
|
551
508
|
}
|
|
@@ -577,12 +534,6 @@ namespace DxMessaging.Core
|
|
|
577
534
|
default,
|
|
578
535
|
postProcessor,
|
|
579
536
|
priority
|
|
580
|
-
),
|
|
581
|
-
new MessageRegistrationMetadata(
|
|
582
|
-
null,
|
|
583
|
-
typeof(T),
|
|
584
|
-
MessageRegistrationType.TargetedWithoutTargetingPostProcessor,
|
|
585
|
-
priority
|
|
586
537
|
)
|
|
587
538
|
);
|
|
588
539
|
}
|
|
@@ -614,12 +565,6 @@ namespace DxMessaging.Core
|
|
|
614
565
|
default,
|
|
615
566
|
postProcessor,
|
|
616
567
|
priority
|
|
617
|
-
),
|
|
618
|
-
new MessageRegistrationMetadata(
|
|
619
|
-
null,
|
|
620
|
-
typeof(T),
|
|
621
|
-
MessageRegistrationType.TargetedWithoutTargetingPostProcessor,
|
|
622
|
-
priority
|
|
623
568
|
)
|
|
624
569
|
);
|
|
625
570
|
}
|
|
@@ -657,12 +602,6 @@ namespace DxMessaging.Core
|
|
|
657
602
|
RegistrationKind.UntargetedHandlerAction,
|
|
658
603
|
untargetedHandler,
|
|
659
604
|
priority
|
|
660
|
-
),
|
|
661
|
-
new MessageRegistrationMetadata(
|
|
662
|
-
null,
|
|
663
|
-
typeof(T),
|
|
664
|
-
MessageRegistrationType.Untargeted,
|
|
665
|
-
priority
|
|
666
605
|
)
|
|
667
606
|
);
|
|
668
607
|
}
|
|
@@ -699,12 +638,6 @@ namespace DxMessaging.Core
|
|
|
699
638
|
RegistrationKind.UntargetedHandlerFast,
|
|
700
639
|
untargetedHandler,
|
|
701
640
|
priority
|
|
702
|
-
),
|
|
703
|
-
new MessageRegistrationMetadata(
|
|
704
|
-
null,
|
|
705
|
-
typeof(T),
|
|
706
|
-
MessageRegistrationType.Untargeted,
|
|
707
|
-
priority
|
|
708
641
|
)
|
|
709
642
|
);
|
|
710
643
|
}
|
|
@@ -732,12 +665,6 @@ namespace DxMessaging.Core
|
|
|
732
665
|
RegistrationKind.UntargetedPostProcessorFast,
|
|
733
666
|
untargetedPostProcessor,
|
|
734
667
|
priority
|
|
735
|
-
),
|
|
736
|
-
new MessageRegistrationMetadata(
|
|
737
|
-
null,
|
|
738
|
-
typeof(T),
|
|
739
|
-
MessageRegistrationType.UntargetedPostProcessor,
|
|
740
|
-
priority
|
|
741
668
|
)
|
|
742
669
|
);
|
|
743
670
|
}
|
|
@@ -760,12 +687,6 @@ namespace DxMessaging.Core
|
|
|
760
687
|
source,
|
|
761
688
|
broadcastHandler,
|
|
762
689
|
priority
|
|
763
|
-
),
|
|
764
|
-
new MessageRegistrationMetadata(
|
|
765
|
-
source,
|
|
766
|
-
typeof(T),
|
|
767
|
-
MessageRegistrationType.Broadcast,
|
|
768
|
-
priority
|
|
769
690
|
)
|
|
770
691
|
);
|
|
771
692
|
}
|
|
@@ -788,12 +709,6 @@ namespace DxMessaging.Core
|
|
|
788
709
|
source,
|
|
789
710
|
broadcastHandler,
|
|
790
711
|
priority
|
|
791
|
-
),
|
|
792
|
-
new MessageRegistrationMetadata(
|
|
793
|
-
source,
|
|
794
|
-
typeof(T),
|
|
795
|
-
MessageRegistrationType.Broadcast,
|
|
796
|
-
priority
|
|
797
712
|
)
|
|
798
713
|
);
|
|
799
714
|
}
|
|
@@ -817,12 +732,6 @@ namespace DxMessaging.Core
|
|
|
817
732
|
source,
|
|
818
733
|
broadcastPostProcessor,
|
|
819
734
|
priority
|
|
820
|
-
),
|
|
821
|
-
new MessageRegistrationMetadata(
|
|
822
|
-
source,
|
|
823
|
-
typeof(T),
|
|
824
|
-
MessageRegistrationType.BroadcastPostProcessor,
|
|
825
|
-
priority
|
|
826
735
|
)
|
|
827
736
|
);
|
|
828
737
|
}
|
|
@@ -845,12 +754,6 @@ namespace DxMessaging.Core
|
|
|
845
754
|
source,
|
|
846
755
|
broadcastPostProcessor,
|
|
847
756
|
priority
|
|
848
|
-
),
|
|
849
|
-
new MessageRegistrationMetadata(
|
|
850
|
-
source,
|
|
851
|
-
typeof(T),
|
|
852
|
-
MessageRegistrationType.BroadcastPostProcessor,
|
|
853
|
-
priority
|
|
854
757
|
)
|
|
855
758
|
);
|
|
856
759
|
}
|
|
@@ -1002,12 +905,6 @@ namespace DxMessaging.Core
|
|
|
1002
905
|
source,
|
|
1003
906
|
broadcastPostProcessor,
|
|
1004
907
|
priority
|
|
1005
|
-
),
|
|
1006
|
-
new MessageRegistrationMetadata(
|
|
1007
|
-
source,
|
|
1008
|
-
typeof(T),
|
|
1009
|
-
MessageRegistrationType.BroadcastPostProcessor,
|
|
1010
|
-
priority
|
|
1011
908
|
)
|
|
1012
909
|
);
|
|
1013
910
|
}
|
|
@@ -1038,12 +935,6 @@ namespace DxMessaging.Core
|
|
|
1038
935
|
source,
|
|
1039
936
|
broadcastPostProcessor,
|
|
1040
937
|
priority
|
|
1041
|
-
),
|
|
1042
|
-
new MessageRegistrationMetadata(
|
|
1043
|
-
source,
|
|
1044
|
-
typeof(T),
|
|
1045
|
-
MessageRegistrationType.BroadcastPostProcessor,
|
|
1046
|
-
priority
|
|
1047
938
|
)
|
|
1048
939
|
);
|
|
1049
940
|
}
|
|
@@ -1166,12 +1057,6 @@ namespace DxMessaging.Core
|
|
|
1166
1057
|
default,
|
|
1167
1058
|
broadcastHandler,
|
|
1168
1059
|
priority
|
|
1169
|
-
),
|
|
1170
|
-
new MessageRegistrationMetadata(
|
|
1171
|
-
null,
|
|
1172
|
-
typeof(T),
|
|
1173
|
-
MessageRegistrationType.BroadcastWithoutSource,
|
|
1174
|
-
priority
|
|
1175
1060
|
)
|
|
1176
1061
|
);
|
|
1177
1062
|
}
|
|
@@ -1204,12 +1089,6 @@ namespace DxMessaging.Core
|
|
|
1204
1089
|
default,
|
|
1205
1090
|
broadcastHandler,
|
|
1206
1091
|
priority
|
|
1207
|
-
),
|
|
1208
|
-
new MessageRegistrationMetadata(
|
|
1209
|
-
null,
|
|
1210
|
-
typeof(T),
|
|
1211
|
-
MessageRegistrationType.BroadcastWithoutSource,
|
|
1212
|
-
priority
|
|
1213
1092
|
)
|
|
1214
1093
|
);
|
|
1215
1094
|
}
|
|
@@ -1247,12 +1126,6 @@ namespace DxMessaging.Core
|
|
|
1247
1126
|
default,
|
|
1248
1127
|
broadcastHandler,
|
|
1249
1128
|
priority
|
|
1250
|
-
),
|
|
1251
|
-
new MessageRegistrationMetadata(
|
|
1252
|
-
null,
|
|
1253
|
-
typeof(T),
|
|
1254
|
-
MessageRegistrationType.BroadcastWithoutSourcePostProcessor,
|
|
1255
|
-
priority
|
|
1256
1129
|
)
|
|
1257
1130
|
);
|
|
1258
1131
|
}
|
|
@@ -1285,12 +1158,6 @@ namespace DxMessaging.Core
|
|
|
1285
1158
|
default,
|
|
1286
1159
|
broadcastHandler,
|
|
1287
1160
|
priority
|
|
1288
|
-
),
|
|
1289
|
-
new MessageRegistrationMetadata(
|
|
1290
|
-
null,
|
|
1291
|
-
typeof(T),
|
|
1292
|
-
MessageRegistrationType.BroadcastWithoutSourcePostProcessor,
|
|
1293
|
-
priority
|
|
1294
1161
|
)
|
|
1295
1162
|
);
|
|
1296
1163
|
}
|
|
@@ -1321,12 +1188,6 @@ namespace DxMessaging.Core
|
|
|
1321
1188
|
acceptAllUntargeted,
|
|
1322
1189
|
acceptAllTargeted,
|
|
1323
1190
|
acceptAllBroadcast
|
|
1324
|
-
),
|
|
1325
|
-
new MessageRegistrationMetadata(
|
|
1326
|
-
null,
|
|
1327
|
-
typeof(IMessage),
|
|
1328
|
-
MessageRegistrationType.GlobalAcceptAll,
|
|
1329
|
-
0
|
|
1330
1191
|
)
|
|
1331
1192
|
);
|
|
1332
1193
|
}
|
|
@@ -1366,12 +1227,6 @@ namespace DxMessaging.Core
|
|
|
1366
1227
|
acceptAllUntargeted,
|
|
1367
1228
|
acceptAllTargeted,
|
|
1368
1229
|
acceptAllBroadcast
|
|
1369
|
-
),
|
|
1370
|
-
new MessageRegistrationMetadata(
|
|
1371
|
-
null,
|
|
1372
|
-
typeof(IMessage),
|
|
1373
|
-
MessageRegistrationType.GlobalAcceptAll,
|
|
1374
|
-
0
|
|
1375
1230
|
)
|
|
1376
1231
|
);
|
|
1377
1232
|
}
|
|
@@ -1395,18 +1250,7 @@ namespace DxMessaging.Core
|
|
|
1395
1250
|
}
|
|
1396
1251
|
|
|
1397
1252
|
return InternalRegister(
|
|
1398
|
-
new
|
|
1399
|
-
this,
|
|
1400
|
-
RegistrationKind.UntargetedInterceptor,
|
|
1401
|
-
interceptor,
|
|
1402
|
-
priority
|
|
1403
|
-
),
|
|
1404
|
-
new MessageRegistrationMetadata(
|
|
1405
|
-
null,
|
|
1406
|
-
typeof(T),
|
|
1407
|
-
MessageRegistrationType.UntargetedInterceptor,
|
|
1408
|
-
priority
|
|
1409
|
-
)
|
|
1253
|
+
new UntargetedInterceptorRegistration<T>(this, interceptor, priority)
|
|
1410
1254
|
);
|
|
1411
1255
|
}
|
|
1412
1256
|
|
|
@@ -1429,19 +1273,7 @@ namespace DxMessaging.Core
|
|
|
1429
1273
|
}
|
|
1430
1274
|
|
|
1431
1275
|
return InternalRegister(
|
|
1432
|
-
new
|
|
1433
|
-
this,
|
|
1434
|
-
RegistrationKind.BroadcastInterceptor,
|
|
1435
|
-
default,
|
|
1436
|
-
interceptor,
|
|
1437
|
-
priority
|
|
1438
|
-
),
|
|
1439
|
-
new MessageRegistrationMetadata(
|
|
1440
|
-
null,
|
|
1441
|
-
typeof(T),
|
|
1442
|
-
MessageRegistrationType.BroadcastInterceptor,
|
|
1443
|
-
priority
|
|
1444
|
-
)
|
|
1276
|
+
new BroadcastInterceptorRegistration<T>(this, interceptor, priority)
|
|
1445
1277
|
);
|
|
1446
1278
|
}
|
|
1447
1279
|
|
|
@@ -1464,19 +1296,7 @@ namespace DxMessaging.Core
|
|
|
1464
1296
|
}
|
|
1465
1297
|
|
|
1466
1298
|
return InternalRegister(
|
|
1467
|
-
new
|
|
1468
|
-
this,
|
|
1469
|
-
RegistrationKind.TargetedInterceptor,
|
|
1470
|
-
default,
|
|
1471
|
-
interceptor,
|
|
1472
|
-
priority
|
|
1473
|
-
),
|
|
1474
|
-
new MessageRegistrationMetadata(
|
|
1475
|
-
null,
|
|
1476
|
-
typeof(T),
|
|
1477
|
-
MessageRegistrationType.TargetedInterceptor,
|
|
1478
|
-
priority
|
|
1479
|
-
)
|
|
1299
|
+
new TargetedInterceptorRegistration<T>(this, interceptor, priority)
|
|
1480
1300
|
);
|
|
1481
1301
|
}
|
|
1482
1302
|
|
|
@@ -1484,29 +1304,29 @@ namespace DxMessaging.Core
|
|
|
1484
1304
|
/// Handles the actual [de]registration wrapping and (potential) lazy execution.
|
|
1485
1305
|
/// </summary>
|
|
1486
1306
|
/// <param name="registration">The unified per-handle registration object the public Register* method built. Calling <see cref="Registration.Register"/> (re)registers the handler on the bus and returns the matching de-registration.</param>
|
|
1487
|
-
/// <param name="metadata">Registration metadata recorded for the diagnostics inspector overlay and the registration-count warning.</param>
|
|
1488
1307
|
/// <returns>A handle that allows for registration and de-registration.</returns>
|
|
1489
|
-
private MessageRegistrationHandle InternalRegister(
|
|
1490
|
-
Registration registration,
|
|
1491
|
-
MessageRegistrationMetadata metadata
|
|
1492
|
-
)
|
|
1308
|
+
private MessageRegistrationHandle InternalRegister(Registration registration)
|
|
1493
1309
|
{
|
|
1310
|
+
int slotIndex = AllocateSlot();
|
|
1494
1311
|
MessageRegistrationHandle handle =
|
|
1495
|
-
MessageRegistrationHandle.CreateMessageRegistrationHandle();
|
|
1496
|
-
|
|
1312
|
+
MessageRegistrationHandle.CreateMessageRegistrationHandle(slotIndex);
|
|
1497
1313
|
registration.Handle = handle;
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1314
|
+
ref RegistrationSlot slot = ref _slots[slotIndex];
|
|
1315
|
+
slot.Id = handle.Id;
|
|
1316
|
+
slot.Registration = registration;
|
|
1317
|
+
slot.Previous = _registrationTail;
|
|
1318
|
+
slot.Next = -1;
|
|
1319
|
+
slot.NextFree = -1;
|
|
1320
|
+
if (_registrationTail >= 0)
|
|
1321
|
+
{
|
|
1322
|
+
_slots[_registrationTail].Next = slotIndex;
|
|
1323
|
+
}
|
|
1324
|
+
else
|
|
1325
|
+
{
|
|
1326
|
+
_registrationHead = slotIndex;
|
|
1327
|
+
}
|
|
1328
|
+
_registrationTail = slotIndex;
|
|
1329
|
+
++_registrationCount;
|
|
1510
1330
|
// Generally, registrations should take place before all calls to enable.
|
|
1511
1331
|
// Just in case, though, register immediately if already enabled. We do not
|
|
1512
1332
|
// register at staging time when disabled (the owner might not be awake), so
|
|
@@ -1515,7 +1335,7 @@ namespace DxMessaging.Core
|
|
|
1515
1335
|
if (_enabled)
|
|
1516
1336
|
{
|
|
1517
1337
|
MessageHandler.HandlerDeregistration actualDeregistration = registration.Register();
|
|
1518
|
-
AddDeregistration(handle, actualDeregistration);
|
|
1338
|
+
AddDeregistration(slotIndex, handle.Id, actualDeregistration);
|
|
1519
1339
|
}
|
|
1520
1340
|
|
|
1521
1341
|
return handle;
|
|
@@ -1540,7 +1360,7 @@ namespace DxMessaging.Core
|
|
|
1540
1360
|
return;
|
|
1541
1361
|
}
|
|
1542
1362
|
|
|
1543
|
-
if (
|
|
1363
|
+
if (_registrationCount > 0)
|
|
1544
1364
|
{
|
|
1545
1365
|
// Replay staged registrations in original registration order
|
|
1546
1366
|
// (via _registrationOrder) rather than in
|
|
@@ -1569,13 +1389,13 @@ namespace DxMessaging.Core
|
|
|
1569
1389
|
/// </example>
|
|
1570
1390
|
public void Disable()
|
|
1571
1391
|
{
|
|
1572
|
-
if (!_enabled &&
|
|
1392
|
+
if (!_enabled && _deregistrationCount == 0)
|
|
1573
1393
|
{
|
|
1574
1394
|
return;
|
|
1575
1395
|
}
|
|
1576
1396
|
|
|
1577
1397
|
Exception deregistrationException = InvokeDeregistrationQueue();
|
|
1578
|
-
_enabled =
|
|
1398
|
+
_enabled = _deregistrationCount > 0;
|
|
1579
1399
|
if (deregistrationException != null)
|
|
1580
1400
|
{
|
|
1581
1401
|
ExceptionDispatchInfo.Capture(deregistrationException).Throw();
|
|
@@ -1598,13 +1418,12 @@ namespace DxMessaging.Core
|
|
|
1598
1418
|
if (deregistrationException == null)
|
|
1599
1419
|
{
|
|
1600
1420
|
_enabled = false;
|
|
1601
|
-
|
|
1602
|
-
_registrationOrder?.Clear();
|
|
1421
|
+
ClearRegistrationArena();
|
|
1603
1422
|
ClearDiagnosticState();
|
|
1604
1423
|
return;
|
|
1605
1424
|
}
|
|
1606
1425
|
|
|
1607
|
-
_enabled =
|
|
1426
|
+
_enabled = _deregistrationCount > 0;
|
|
1608
1427
|
PruneRegistrationStateToFailedDeregistrations();
|
|
1609
1428
|
ExceptionDispatchInfo.Capture(deregistrationException).Throw();
|
|
1610
1429
|
}
|
|
@@ -1627,16 +1446,21 @@ namespace DxMessaging.Core
|
|
|
1627
1446
|
bool rebindActiveRegistrations =
|
|
1628
1447
|
effectiveMode == MessageBusRebindMode.RebindActive
|
|
1629
1448
|
&& _enabled
|
|
1630
|
-
&&
|
|
1449
|
+
&& _deregistrationCount > 0;
|
|
1631
1450
|
if (sameBus && !rebindActiveRegistrations)
|
|
1632
1451
|
{
|
|
1633
1452
|
return;
|
|
1634
1453
|
}
|
|
1635
1454
|
|
|
1636
1455
|
IMessageBus previousMessageBus = _messageBus;
|
|
1637
|
-
List<MessageRegistrationHandle> activeRetargetHandles =
|
|
1638
|
-
|
|
1639
|
-
|
|
1456
|
+
List<MessageRegistrationHandle> activeRetargetHandles = null;
|
|
1457
|
+
if (rebindActiveRegistrations)
|
|
1458
|
+
{
|
|
1459
|
+
activeRetargetHandles = _activeRetargetHandles ??=
|
|
1460
|
+
new List<MessageRegistrationHandle>();
|
|
1461
|
+
activeRetargetHandles.Clear();
|
|
1462
|
+
QueueActiveHandles(activeRetargetHandles);
|
|
1463
|
+
}
|
|
1640
1464
|
if (rebindActiveRegistrations)
|
|
1641
1465
|
{
|
|
1642
1466
|
Exception deregistrationException = InvokeDeregistrationQueue();
|
|
@@ -1646,7 +1470,7 @@ namespace DxMessaging.Core
|
|
|
1646
1470
|
previousMessageBus,
|
|
1647
1471
|
activeRetargetHandles
|
|
1648
1472
|
);
|
|
1649
|
-
_enabled =
|
|
1473
|
+
_enabled = _deregistrationCount > 0;
|
|
1650
1474
|
ExceptionDispatchInfo.Capture(deregistrationException).Throw();
|
|
1651
1475
|
}
|
|
1652
1476
|
|
|
@@ -1655,7 +1479,7 @@ namespace DxMessaging.Core
|
|
|
1655
1479
|
|
|
1656
1480
|
_messageBus = messageBus;
|
|
1657
1481
|
|
|
1658
|
-
if (rebindActiveRegistrations &&
|
|
1482
|
+
if (rebindActiveRegistrations && _registrationCount > 0)
|
|
1659
1483
|
{
|
|
1660
1484
|
// Mirror Enable(): rebind in original registration order so the
|
|
1661
1485
|
// equal-priority dispatch order survives a bus retarget.
|
|
@@ -1675,20 +1499,32 @@ namespace DxMessaging.Core
|
|
|
1675
1499
|
}
|
|
1676
1500
|
|
|
1677
1501
|
private void AddDeregistration(
|
|
1678
|
-
|
|
1502
|
+
int slotIndex,
|
|
1503
|
+
long id,
|
|
1679
1504
|
MessageHandler.HandlerDeregistration deregistration
|
|
1680
1505
|
)
|
|
1681
1506
|
{
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1507
|
+
if (!TryGetSlot(slotIndex, id, out RegistrationSlot slot))
|
|
1508
|
+
{
|
|
1509
|
+
// The staged registration was removed or its slot was reused while its replay
|
|
1510
|
+
// snapshot was executing. Preserve the returned teardown under the original
|
|
1511
|
+
// identity: consuming it here would lose a throwing teardown instead of keeping it
|
|
1512
|
+
// retryable, while attaching it to the slot would target the new occupant.
|
|
1513
|
+
AddOrphanDeregistration(
|
|
1514
|
+
MessageRegistrationHandle.FromIdentity(id, slotIndex),
|
|
1515
|
+
deregistration
|
|
1516
|
+
);
|
|
1517
|
+
return;
|
|
1518
|
+
}
|
|
1519
|
+
|
|
1520
|
+
object existing = slot.Deregistration;
|
|
1521
|
+
if (existing == null)
|
|
1687
1522
|
{
|
|
1523
|
+
_slots[slotIndex].Deregistration = deregistration;
|
|
1524
|
+
++_deregistrationCount;
|
|
1688
1525
|
return;
|
|
1689
1526
|
}
|
|
1690
1527
|
|
|
1691
|
-
object existing = _deregistrations[handle];
|
|
1692
1528
|
if (existing is PendingDeregistration pending)
|
|
1693
1529
|
{
|
|
1694
1530
|
pending.Add(deregistration);
|
|
@@ -1701,7 +1537,33 @@ namespace DxMessaging.Core
|
|
|
1701
1537
|
PendingDeregistration promoted = new();
|
|
1702
1538
|
promoted.Add((MessageHandler.HandlerDeregistration)existing);
|
|
1703
1539
|
promoted.Add(deregistration);
|
|
1704
|
-
|
|
1540
|
+
_slots[slotIndex].Deregistration = promoted;
|
|
1541
|
+
}
|
|
1542
|
+
|
|
1543
|
+
private void AddOrphanDeregistration(
|
|
1544
|
+
MessageRegistrationHandle handle,
|
|
1545
|
+
MessageHandler.HandlerDeregistration deregistration
|
|
1546
|
+
)
|
|
1547
|
+
{
|
|
1548
|
+
Dictionary<MessageRegistrationHandle, object> orphans = _orphanDeregistrations ??=
|
|
1549
|
+
new Dictionary<MessageRegistrationHandle, object>();
|
|
1550
|
+
if (!orphans.TryGetValue(handle, out object existing))
|
|
1551
|
+
{
|
|
1552
|
+
orphans.Add(handle, deregistration);
|
|
1553
|
+
++_deregistrationCount;
|
|
1554
|
+
return;
|
|
1555
|
+
}
|
|
1556
|
+
|
|
1557
|
+
if (existing is PendingDeregistration pending)
|
|
1558
|
+
{
|
|
1559
|
+
pending.Add(deregistration);
|
|
1560
|
+
return;
|
|
1561
|
+
}
|
|
1562
|
+
|
|
1563
|
+
PendingDeregistration promoted = new();
|
|
1564
|
+
promoted.Add((MessageHandler.HandlerDeregistration)existing);
|
|
1565
|
+
promoted.Add(deregistration);
|
|
1566
|
+
orphans[handle] = promoted;
|
|
1705
1567
|
}
|
|
1706
1568
|
|
|
1707
1569
|
// Logical de-registration count for a _deregistrations value (inline object == 1).
|
|
@@ -1750,10 +1612,31 @@ namespace DxMessaging.Core
|
|
|
1750
1612
|
|
|
1751
1613
|
private Dictionary<MessageRegistrationHandle, int> SnapshotDeregistrationCounts()
|
|
1752
1614
|
{
|
|
1753
|
-
Dictionary<MessageRegistrationHandle, int> snapshot =
|
|
1754
|
-
|
|
1615
|
+
Dictionary<MessageRegistrationHandle, int> snapshot = _rollbackCounts ??=
|
|
1616
|
+
new Dictionary<MessageRegistrationHandle, int>();
|
|
1617
|
+
snapshot.Clear();
|
|
1618
|
+
for (
|
|
1619
|
+
int slotIndex = _registrationHead;
|
|
1620
|
+
slotIndex >= 0;
|
|
1621
|
+
slotIndex = _slots[slotIndex].Next
|
|
1622
|
+
)
|
|
1623
|
+
{
|
|
1624
|
+
RegistrationSlot slot = _slots[slotIndex];
|
|
1625
|
+
if (slot.Deregistration != null)
|
|
1626
|
+
{
|
|
1627
|
+
snapshot[MessageRegistrationHandle.FromIdentity(slot.Id, slotIndex)] =
|
|
1628
|
+
DeregistrationCount(slot.Deregistration);
|
|
1629
|
+
}
|
|
1630
|
+
}
|
|
1631
|
+
|
|
1632
|
+
if (_orphanDeregistrations != null)
|
|
1755
1633
|
{
|
|
1756
|
-
|
|
1634
|
+
foreach (
|
|
1635
|
+
KeyValuePair<MessageRegistrationHandle, object> entry in _orphanDeregistrations
|
|
1636
|
+
)
|
|
1637
|
+
{
|
|
1638
|
+
snapshot[entry.Key] = DeregistrationCount(entry.Value);
|
|
1639
|
+
}
|
|
1757
1640
|
}
|
|
1758
1641
|
|
|
1759
1642
|
return snapshot;
|
|
@@ -1791,9 +1674,9 @@ namespace DxMessaging.Core
|
|
|
1791
1674
|
private void RestoreRegistrationsAfterRetargetFailure(IMessageBus previousMessageBus)
|
|
1792
1675
|
{
|
|
1793
1676
|
_messageBus = previousMessageBus;
|
|
1794
|
-
if (
|
|
1677
|
+
if (_registrationCount == 0)
|
|
1795
1678
|
{
|
|
1796
|
-
_enabled =
|
|
1679
|
+
_enabled = _deregistrationCount > 0;
|
|
1797
1680
|
return;
|
|
1798
1681
|
}
|
|
1799
1682
|
|
|
@@ -1805,7 +1688,7 @@ namespace DxMessaging.Core
|
|
|
1805
1688
|
}
|
|
1806
1689
|
catch (Exception restoreException)
|
|
1807
1690
|
{
|
|
1808
|
-
_enabled =
|
|
1691
|
+
_enabled = _deregistrationCount > 0;
|
|
1809
1692
|
if (MessagingDebug.enabled)
|
|
1810
1693
|
{
|
|
1811
1694
|
MessagingDebug.Log(
|
|
@@ -1819,15 +1702,16 @@ namespace DxMessaging.Core
|
|
|
1819
1702
|
|
|
1820
1703
|
private void QueueRegistrationsInOrder()
|
|
1821
1704
|
{
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
for (
|
|
1705
|
+
List<StagedRegistration> queue = GetRegistrationReplayQueue();
|
|
1706
|
+
queue.Clear();
|
|
1707
|
+
for (
|
|
1708
|
+
int slotIndex = _registrationHead;
|
|
1709
|
+
slotIndex >= 0;
|
|
1710
|
+
slotIndex = _slots[slotIndex].Next
|
|
1711
|
+
)
|
|
1825
1712
|
{
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
{
|
|
1829
|
-
_registrationReplayQueue.Add(new StagedRegistration(handle, registration));
|
|
1830
|
-
}
|
|
1713
|
+
RegistrationSlot slot = _slots[slotIndex];
|
|
1714
|
+
queue.Add(new StagedRegistration(slotIndex, slot.Id, slot.Registration));
|
|
1831
1715
|
}
|
|
1832
1716
|
}
|
|
1833
1717
|
|
|
@@ -1835,40 +1719,42 @@ namespace DxMessaging.Core
|
|
|
1835
1719
|
List<MessageRegistrationHandle> activeRetargetHandles
|
|
1836
1720
|
)
|
|
1837
1721
|
{
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
for (
|
|
1722
|
+
List<StagedRegistration> queue = GetRegistrationReplayQueue();
|
|
1723
|
+
queue.Clear();
|
|
1724
|
+
for (
|
|
1725
|
+
int slotIndex = _registrationHead;
|
|
1726
|
+
slotIndex >= 0;
|
|
1727
|
+
slotIndex = _slots[slotIndex].Next
|
|
1728
|
+
)
|
|
1841
1729
|
{
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|| _deregistrations.ContainsKey(handle)
|
|
1846
|
-
|| !_registrations.TryGetValue(handle, out Registration registration)
|
|
1847
|
-
)
|
|
1730
|
+
RegistrationSlot slot = _slots[slotIndex];
|
|
1731
|
+
MessageRegistrationHandle handle = slot.Registration.Handle;
|
|
1732
|
+
if (!activeRetargetHandles.Contains(handle) || slot.Deregistration != null)
|
|
1848
1733
|
{
|
|
1849
1734
|
continue;
|
|
1850
1735
|
}
|
|
1851
1736
|
|
|
1852
|
-
|
|
1737
|
+
queue.Add(new StagedRegistration(slotIndex, slot.Id, slot.Registration));
|
|
1853
1738
|
}
|
|
1854
1739
|
}
|
|
1855
1740
|
|
|
1856
1741
|
private void QueueRegistrationsWithoutRetryableDeregistrationsInOrder()
|
|
1857
1742
|
{
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
for (
|
|
1743
|
+
List<StagedRegistration> queue = GetRegistrationReplayQueue();
|
|
1744
|
+
queue.Clear();
|
|
1745
|
+
for (
|
|
1746
|
+
int slotIndex = _registrationHead;
|
|
1747
|
+
slotIndex >= 0;
|
|
1748
|
+
slotIndex = _slots[slotIndex].Next
|
|
1749
|
+
)
|
|
1861
1750
|
{
|
|
1862
|
-
|
|
1863
|
-
if (
|
|
1864
|
-
_deregistrations.ContainsKey(handle)
|
|
1865
|
-
|| !_registrations.TryGetValue(handle, out Registration registration)
|
|
1866
|
-
)
|
|
1751
|
+
RegistrationSlot slot = _slots[slotIndex];
|
|
1752
|
+
if (slot.Deregistration != null)
|
|
1867
1753
|
{
|
|
1868
1754
|
continue;
|
|
1869
1755
|
}
|
|
1870
1756
|
|
|
1871
|
-
|
|
1757
|
+
queue.Add(new StagedRegistration(slotIndex, slot.Id, slot.Registration));
|
|
1872
1758
|
}
|
|
1873
1759
|
}
|
|
1874
1760
|
|
|
@@ -1876,7 +1762,7 @@ namespace DxMessaging.Core
|
|
|
1876
1762
|
{
|
|
1877
1763
|
try
|
|
1878
1764
|
{
|
|
1879
|
-
foreach (StagedRegistration staged in
|
|
1765
|
+
foreach (StagedRegistration staged in GetRegistrationReplayQueue())
|
|
1880
1766
|
{
|
|
1881
1767
|
Registration registration = staged.Registration;
|
|
1882
1768
|
if (registration == null)
|
|
@@ -1886,12 +1772,12 @@ namespace DxMessaging.Core
|
|
|
1886
1772
|
|
|
1887
1773
|
MessageHandler.HandlerDeregistration actualDeregistration =
|
|
1888
1774
|
registration.Register();
|
|
1889
|
-
AddDeregistration(staged.
|
|
1775
|
+
AddDeregistration(staged.Slot, staged.Id, actualDeregistration);
|
|
1890
1776
|
}
|
|
1891
1777
|
}
|
|
1892
1778
|
finally
|
|
1893
1779
|
{
|
|
1894
|
-
_registrationReplayQueue
|
|
1780
|
+
_registrationReplayQueue?.Clear();
|
|
1895
1781
|
}
|
|
1896
1782
|
}
|
|
1897
1783
|
|
|
@@ -1905,12 +1791,14 @@ namespace DxMessaging.Core
|
|
|
1905
1791
|
/// </summary>
|
|
1906
1792
|
private readonly struct StagedRegistration
|
|
1907
1793
|
{
|
|
1908
|
-
public readonly
|
|
1794
|
+
public readonly int Slot;
|
|
1795
|
+
public readonly long Id;
|
|
1909
1796
|
public readonly Registration Registration;
|
|
1910
1797
|
|
|
1911
|
-
public StagedRegistration(
|
|
1798
|
+
public StagedRegistration(int slot, long id, Registration registration)
|
|
1912
1799
|
{
|
|
1913
|
-
|
|
1800
|
+
Slot = slot;
|
|
1801
|
+
Id = id;
|
|
1914
1802
|
Registration = registration;
|
|
1915
1803
|
}
|
|
1916
1804
|
}
|
|
@@ -1919,22 +1807,76 @@ namespace DxMessaging.Core
|
|
|
1919
1807
|
Dictionary<MessageRegistrationHandle, int> baselineCounts = null
|
|
1920
1808
|
)
|
|
1921
1809
|
{
|
|
1922
|
-
if (
|
|
1810
|
+
if (_deregistrationCount == 0)
|
|
1923
1811
|
{
|
|
1924
1812
|
return null;
|
|
1925
1813
|
}
|
|
1926
1814
|
|
|
1927
1815
|
bool scopedToAddedDeregistrations = baselineCounts != null;
|
|
1928
|
-
|
|
1929
|
-
|
|
1816
|
+
List<TeardownIdentity> teardownQueue = _teardownQueue ??= new List<TeardownIdentity>();
|
|
1817
|
+
teardownQueue.Clear();
|
|
1818
|
+
for (
|
|
1819
|
+
int slotIndex = _registrationHead;
|
|
1820
|
+
slotIndex >= 0;
|
|
1821
|
+
slotIndex = _slots[slotIndex].Next
|
|
1822
|
+
)
|
|
1823
|
+
{
|
|
1824
|
+
RegistrationSlot slot = _slots[slotIndex];
|
|
1825
|
+
if (slot.Deregistration != null)
|
|
1826
|
+
{
|
|
1827
|
+
teardownQueue.Add(new TeardownIdentity(slotIndex, slot.Id, isOrphan: false));
|
|
1828
|
+
}
|
|
1829
|
+
}
|
|
1830
|
+
|
|
1831
|
+
bool hasOrphanSnapshot =
|
|
1832
|
+
_orphanDeregistrations != null && _orphanDeregistrations.Count > 0;
|
|
1833
|
+
if (hasOrphanSnapshot)
|
|
1834
|
+
{
|
|
1835
|
+
foreach (MessageRegistrationHandle handle in _orphanDeregistrations.Keys)
|
|
1836
|
+
{
|
|
1837
|
+
teardownQueue.Add(new TeardownIdentity(handle.Slot, handle.Id, isOrphan: true));
|
|
1838
|
+
}
|
|
1839
|
+
}
|
|
1840
|
+
|
|
1841
|
+
// Global handle ids are monotonic and therefore encode original registration order.
|
|
1842
|
+
// Capture and sort BEFORE invoking anything: reentrant teardown additions are deferred
|
|
1843
|
+
// to the next pass rather than joining this snapshot.
|
|
1844
|
+
if (hasOrphanSnapshot)
|
|
1845
|
+
{
|
|
1846
|
+
teardownQueue.Sort(TeardownIdentityComparer.Instance);
|
|
1847
|
+
}
|
|
1930
1848
|
Exception firstException = null;
|
|
1931
1849
|
try
|
|
1932
1850
|
{
|
|
1933
|
-
foreach (
|
|
1851
|
+
foreach (TeardownIdentity identity in teardownQueue)
|
|
1934
1852
|
{
|
|
1935
|
-
|
|
1853
|
+
MessageRegistrationHandle handle = MessageRegistrationHandle.FromIdentity(
|
|
1854
|
+
identity.Id,
|
|
1855
|
+
identity.Slot
|
|
1856
|
+
);
|
|
1857
|
+
object value;
|
|
1858
|
+
if (identity.IsOrphan)
|
|
1936
1859
|
{
|
|
1937
|
-
|
|
1860
|
+
if (
|
|
1861
|
+
_orphanDeregistrations == null
|
|
1862
|
+
|| !_orphanDeregistrations.TryGetValue(handle, out value)
|
|
1863
|
+
)
|
|
1864
|
+
{
|
|
1865
|
+
continue;
|
|
1866
|
+
}
|
|
1867
|
+
}
|
|
1868
|
+
else
|
|
1869
|
+
{
|
|
1870
|
+
if (!TryGetSlot(identity.Slot, identity.Id, out RegistrationSlot slot))
|
|
1871
|
+
{
|
|
1872
|
+
continue;
|
|
1873
|
+
}
|
|
1874
|
+
|
|
1875
|
+
value = slot.Deregistration;
|
|
1876
|
+
if (value == null)
|
|
1877
|
+
{
|
|
1878
|
+
continue;
|
|
1879
|
+
}
|
|
1938
1880
|
}
|
|
1939
1881
|
|
|
1940
1882
|
int startIndex = 0;
|
|
@@ -1963,13 +1905,24 @@ namespace DxMessaging.Core
|
|
|
1963
1905
|
|
|
1964
1906
|
if (shouldRemove)
|
|
1965
1907
|
{
|
|
1966
|
-
|
|
1908
|
+
if (identity.IsOrphan)
|
|
1909
|
+
{
|
|
1910
|
+
_orphanDeregistrations.Remove(handle);
|
|
1911
|
+
--_deregistrationCount;
|
|
1912
|
+
}
|
|
1913
|
+
else if (
|
|
1914
|
+
TryGetSlot(identity.Slot, identity.Id, out RegistrationSlot current)
|
|
1915
|
+
)
|
|
1916
|
+
{
|
|
1917
|
+
_slots[identity.Slot].Deregistration = null;
|
|
1918
|
+
--_deregistrationCount;
|
|
1919
|
+
}
|
|
1967
1920
|
}
|
|
1968
1921
|
}
|
|
1969
1922
|
}
|
|
1970
1923
|
finally
|
|
1971
1924
|
{
|
|
1972
|
-
|
|
1925
|
+
teardownQueue.Clear();
|
|
1973
1926
|
}
|
|
1974
1927
|
|
|
1975
1928
|
return firstException;
|
|
@@ -1986,7 +1939,7 @@ namespace DxMessaging.Core
|
|
|
1986
1939
|
catch (Exception exception)
|
|
1987
1940
|
{
|
|
1988
1941
|
RollBackDeregistrationsAfterRegistrationFailure(rollbackBaseline);
|
|
1989
|
-
_enabled =
|
|
1942
|
+
_enabled = _deregistrationCount > 0;
|
|
1990
1943
|
ExceptionDispatchInfo.Capture(exception).Throw();
|
|
1991
1944
|
throw;
|
|
1992
1945
|
}
|
|
@@ -1996,7 +1949,7 @@ namespace DxMessaging.Core
|
|
|
1996
1949
|
Dictionary<MessageRegistrationHandle, int> rollbackBaseline
|
|
1997
1950
|
)
|
|
1998
1951
|
{
|
|
1999
|
-
if (
|
|
1952
|
+
if (_deregistrationCount == 0)
|
|
2000
1953
|
{
|
|
2001
1954
|
return;
|
|
2002
1955
|
}
|
|
@@ -2014,7 +1967,6 @@ namespace DxMessaging.Core
|
|
|
2014
1967
|
|
|
2015
1968
|
private void ClearDiagnosticState()
|
|
2016
1969
|
{
|
|
2017
|
-
_metadata.Clear();
|
|
2018
1970
|
// Clear through the backing fields so an inactive (never-materialized)
|
|
2019
1971
|
// diagnostics collection is not allocated merely to be emptied.
|
|
2020
1972
|
_callCountsBacking?.Clear();
|
|
@@ -2023,19 +1975,20 @@ namespace DxMessaging.Core
|
|
|
2023
1975
|
|
|
2024
1976
|
private void PruneRegistrationStateToFailedDeregistrations()
|
|
2025
1977
|
{
|
|
2026
|
-
|
|
1978
|
+
int slotIndex = _registrationTail;
|
|
1979
|
+
while (slotIndex >= 0)
|
|
2027
1980
|
{
|
|
2028
|
-
|
|
2029
|
-
if (
|
|
1981
|
+
int previous = _slots[slotIndex].Previous;
|
|
1982
|
+
if (_slots[slotIndex].Deregistration == null)
|
|
2030
1983
|
{
|
|
2031
|
-
|
|
1984
|
+
RemoveRegistrationState(slotIndex, _slots[slotIndex].Id);
|
|
2032
1985
|
}
|
|
2033
1986
|
|
|
2034
|
-
|
|
1987
|
+
slotIndex = previous;
|
|
2035
1988
|
}
|
|
2036
1989
|
|
|
2037
1990
|
_emissionBufferBacking?.Clear();
|
|
2038
|
-
if (
|
|
1991
|
+
if (_registrationCount == 0)
|
|
2039
1992
|
{
|
|
2040
1993
|
ClearDiagnosticState();
|
|
2041
1994
|
}
|
|
@@ -2043,16 +1996,51 @@ namespace DxMessaging.Core
|
|
|
2043
1996
|
|
|
2044
1997
|
private bool RemoveRegistrationState(MessageRegistrationHandle handle)
|
|
2045
1998
|
{
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
1999
|
+
return RemoveRegistrationState(handle.Slot, handle.Id);
|
|
2000
|
+
}
|
|
2001
|
+
|
|
2002
|
+
private bool RemoveRegistrationState(int slotIndex, long id)
|
|
2003
|
+
{
|
|
2004
|
+
if (!TryGetSlot(slotIndex, id, out RegistrationSlot slot))
|
|
2005
|
+
{
|
|
2006
|
+
return false;
|
|
2007
|
+
}
|
|
2008
|
+
|
|
2009
|
+
if (slot.Previous >= 0)
|
|
2010
|
+
{
|
|
2011
|
+
_slots[slot.Previous].Next = slot.Next;
|
|
2012
|
+
}
|
|
2013
|
+
else
|
|
2014
|
+
{
|
|
2015
|
+
_registrationHead = slot.Next;
|
|
2016
|
+
}
|
|
2017
|
+
|
|
2018
|
+
if (slot.Next >= 0)
|
|
2019
|
+
{
|
|
2020
|
+
_slots[slot.Next].Previous = slot.Previous;
|
|
2021
|
+
}
|
|
2022
|
+
else
|
|
2023
|
+
{
|
|
2024
|
+
_registrationTail = slot.Previous;
|
|
2025
|
+
}
|
|
2026
|
+
|
|
2027
|
+
MessageRegistrationHandle handle = MessageRegistrationHandle.FromIdentity(
|
|
2028
|
+
id,
|
|
2029
|
+
slotIndex
|
|
2030
|
+
);
|
|
2049
2031
|
_callCountsBacking?.Remove(handle);
|
|
2050
|
-
|
|
2032
|
+
_slots[slotIndex] = default;
|
|
2033
|
+
_slots[slotIndex].Previous = -1;
|
|
2034
|
+
_slots[slotIndex].Next = -1;
|
|
2035
|
+
_slots[slotIndex].NextFree = _freeSlotHead;
|
|
2036
|
+
_freeSlotHead = slotIndex;
|
|
2037
|
+
--_registrationCount;
|
|
2038
|
+
if (_registrationCount == 0)
|
|
2051
2039
|
{
|
|
2052
2040
|
ClearDiagnosticState();
|
|
2053
2041
|
}
|
|
2054
2042
|
|
|
2055
|
-
return
|
|
2043
|
+
return true;
|
|
2056
2044
|
}
|
|
2057
2045
|
|
|
2058
2046
|
/// <summary>
|
|
@@ -2067,7 +2055,14 @@ namespace DxMessaging.Core
|
|
|
2067
2055
|
/// </example>
|
|
2068
2056
|
public void RemoveRegistration(MessageRegistrationHandle handle)
|
|
2069
2057
|
{
|
|
2070
|
-
if (
|
|
2058
|
+
if (!TryGetSlot(handle.Slot, handle.Id, out RegistrationSlot slot))
|
|
2059
|
+
{
|
|
2060
|
+
RemoveOrphanDeregistration(handle);
|
|
2061
|
+
return;
|
|
2062
|
+
}
|
|
2063
|
+
|
|
2064
|
+
object value = slot.Deregistration;
|
|
2065
|
+
if (value != null)
|
|
2071
2066
|
{
|
|
2072
2067
|
Exception deregistrationException = InvokeDeregistration(
|
|
2073
2068
|
value,
|
|
@@ -2076,7 +2071,11 @@ namespace DxMessaging.Core
|
|
|
2076
2071
|
);
|
|
2077
2072
|
if (shouldRemove)
|
|
2078
2073
|
{
|
|
2079
|
-
|
|
2074
|
+
if (TryGetSlot(handle.Slot, handle.Id, out RegistrationSlot current))
|
|
2075
|
+
{
|
|
2076
|
+
_slots[handle.Slot].Deregistration = null;
|
|
2077
|
+
--_deregistrationCount;
|
|
2078
|
+
}
|
|
2080
2079
|
}
|
|
2081
2080
|
|
|
2082
2081
|
if (deregistrationException != null)
|
|
@@ -2091,23 +2090,262 @@ namespace DxMessaging.Core
|
|
|
2091
2090
|
RemoveRegistrationState(handle);
|
|
2092
2091
|
}
|
|
2093
2092
|
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2093
|
+
private void RemoveOrphanDeregistration(MessageRegistrationHandle handle)
|
|
2094
|
+
{
|
|
2095
|
+
if (
|
|
2096
|
+
_orphanDeregistrations == null
|
|
2097
|
+
|| !_orphanDeregistrations.TryGetValue(handle, out object value)
|
|
2098
|
+
)
|
|
2099
|
+
{
|
|
2100
|
+
return;
|
|
2101
|
+
}
|
|
2102
|
+
|
|
2103
|
+
Exception exception = InvokeDeregistration(value, 0, out bool shouldRemove);
|
|
2104
|
+
if (shouldRemove)
|
|
2105
|
+
{
|
|
2106
|
+
_orphanDeregistrations.Remove(handle);
|
|
2107
|
+
--_deregistrationCount;
|
|
2108
|
+
}
|
|
2109
|
+
|
|
2110
|
+
if (exception != null)
|
|
2111
|
+
{
|
|
2112
|
+
ExceptionDispatchInfo.Capture(exception).Throw();
|
|
2113
|
+
}
|
|
2114
|
+
}
|
|
2115
|
+
|
|
2116
|
+
private int AllocateSlot()
|
|
2117
|
+
{
|
|
2118
|
+
if (_freeSlotHead < 0)
|
|
2119
|
+
{
|
|
2120
|
+
int oldLength = _slots.Length;
|
|
2121
|
+
int newLength = oldLength == 0 ? 4 : oldLength << 1;
|
|
2122
|
+
Array.Resize(ref _slots, newLength);
|
|
2123
|
+
for (int i = newLength - 1; i >= oldLength; --i)
|
|
2124
|
+
{
|
|
2125
|
+
_slots[i].Previous = -1;
|
|
2126
|
+
_slots[i].Next = -1;
|
|
2127
|
+
_slots[i].NextFree = _freeSlotHead;
|
|
2128
|
+
_freeSlotHead = i;
|
|
2129
|
+
}
|
|
2130
|
+
}
|
|
2131
|
+
|
|
2132
|
+
int slotIndex = _freeSlotHead;
|
|
2133
|
+
_freeSlotHead = _slots[slotIndex].NextFree;
|
|
2134
|
+
return slotIndex;
|
|
2135
|
+
}
|
|
2136
|
+
|
|
2137
|
+
private bool TryGetSlot(int slotIndex, long id, out RegistrationSlot slot)
|
|
2138
|
+
{
|
|
2139
|
+
if ((uint)slotIndex < (uint)_slots.Length)
|
|
2140
|
+
{
|
|
2141
|
+
slot = _slots[slotIndex];
|
|
2142
|
+
if (slot.Registration != null && slot.Id == id)
|
|
2143
|
+
{
|
|
2144
|
+
return true;
|
|
2145
|
+
}
|
|
2146
|
+
}
|
|
2147
|
+
|
|
2148
|
+
slot = default;
|
|
2149
|
+
return false;
|
|
2150
|
+
}
|
|
2151
|
+
|
|
2152
|
+
private void ClearRegistrationArena()
|
|
2153
|
+
{
|
|
2154
|
+
if (_slots.Length > 0)
|
|
2155
|
+
{
|
|
2156
|
+
Array.Clear(_slots, 0, _slots.Length);
|
|
2157
|
+
_freeSlotHead = -1;
|
|
2158
|
+
for (int i = _slots.Length - 1; i >= 0; --i)
|
|
2159
|
+
{
|
|
2160
|
+
_slots[i].Previous = -1;
|
|
2161
|
+
_slots[i].Next = -1;
|
|
2162
|
+
_slots[i].NextFree = _freeSlotHead;
|
|
2163
|
+
_freeSlotHead = i;
|
|
2164
|
+
}
|
|
2165
|
+
}
|
|
2166
|
+
else
|
|
2167
|
+
{
|
|
2168
|
+
_freeSlotHead = -1;
|
|
2169
|
+
}
|
|
2170
|
+
|
|
2171
|
+
_registrationHead = -1;
|
|
2172
|
+
_registrationTail = -1;
|
|
2173
|
+
_registrationCount = 0;
|
|
2174
|
+
_deregistrationCount = 0;
|
|
2175
|
+
_registrationReplayQueue?.Clear();
|
|
2176
|
+
_teardownQueue?.Clear();
|
|
2177
|
+
_rollbackCounts?.Clear();
|
|
2178
|
+
_activeRetargetHandles?.Clear();
|
|
2179
|
+
_orphanDeregistrations?.Clear();
|
|
2180
|
+
}
|
|
2181
|
+
|
|
2182
|
+
private List<StagedRegistration> GetRegistrationReplayQueue()
|
|
2183
|
+
{
|
|
2184
|
+
return _registrationReplayQueue ??= new List<StagedRegistration>();
|
|
2185
|
+
}
|
|
2186
|
+
|
|
2187
|
+
private void QueueActiveHandles(List<MessageRegistrationHandle> destination)
|
|
2188
|
+
{
|
|
2189
|
+
for (
|
|
2190
|
+
int slotIndex = _registrationHead;
|
|
2191
|
+
slotIndex >= 0;
|
|
2192
|
+
slotIndex = _slots[slotIndex].Next
|
|
2193
|
+
)
|
|
2194
|
+
{
|
|
2195
|
+
RegistrationSlot slot = _slots[slotIndex];
|
|
2196
|
+
if (slot.Deregistration != null)
|
|
2197
|
+
{
|
|
2198
|
+
destination.Add(MessageRegistrationHandle.FromIdentity(slot.Id, slotIndex));
|
|
2199
|
+
}
|
|
2200
|
+
}
|
|
2201
|
+
|
|
2202
|
+
if (_orphanDeregistrations != null)
|
|
2203
|
+
{
|
|
2204
|
+
destination.AddRange(_orphanDeregistrations.Keys);
|
|
2205
|
+
}
|
|
2206
|
+
}
|
|
2207
|
+
|
|
2208
|
+
private struct RegistrationSlot
|
|
2209
|
+
{
|
|
2210
|
+
public Registration Registration;
|
|
2211
|
+
public object Deregistration;
|
|
2212
|
+
public long Id;
|
|
2213
|
+
public int Previous;
|
|
2214
|
+
public int Next;
|
|
2215
|
+
public int NextFree;
|
|
2216
|
+
}
|
|
2217
|
+
|
|
2218
|
+
private readonly struct TeardownIdentity
|
|
2219
|
+
{
|
|
2220
|
+
public readonly int Slot;
|
|
2221
|
+
public readonly long Id;
|
|
2222
|
+
public readonly bool IsOrphan;
|
|
2223
|
+
|
|
2224
|
+
public TeardownIdentity(int slot, long id, bool isOrphan)
|
|
2225
|
+
{
|
|
2226
|
+
Slot = slot;
|
|
2227
|
+
Id = id;
|
|
2228
|
+
IsOrphan = isOrphan;
|
|
2229
|
+
}
|
|
2230
|
+
}
|
|
2231
|
+
|
|
2232
|
+
private sealed class TeardownIdentityComparer : IComparer<TeardownIdentity>
|
|
2233
|
+
{
|
|
2234
|
+
internal static readonly TeardownIdentityComparer Instance = new();
|
|
2235
|
+
|
|
2236
|
+
public int Compare(TeardownIdentity left, TeardownIdentity right)
|
|
2237
|
+
{
|
|
2238
|
+
return left.Id.CompareTo(right.Id);
|
|
2239
|
+
}
|
|
2240
|
+
}
|
|
2241
|
+
|
|
2242
|
+
internal readonly struct RegistrationMetadataView
|
|
2243
|
+
: IEnumerable<KeyValuePair<MessageRegistrationHandle, MessageRegistrationMetadata>>
|
|
2244
|
+
{
|
|
2245
|
+
private readonly MessageRegistrationToken _token;
|
|
2246
|
+
|
|
2247
|
+
internal RegistrationMetadataView(MessageRegistrationToken token)
|
|
2248
|
+
{
|
|
2249
|
+
_token = token;
|
|
2250
|
+
}
|
|
2251
|
+
|
|
2252
|
+
public int Count => _token._registrationCount;
|
|
2253
|
+
|
|
2254
|
+
public bool ContainsKey(MessageRegistrationHandle handle)
|
|
2255
|
+
{
|
|
2256
|
+
return _token.TryGetSlot(handle.Slot, handle.Id, out RegistrationSlot slot);
|
|
2257
|
+
}
|
|
2258
|
+
|
|
2259
|
+
public Enumerator GetEnumerator()
|
|
2260
|
+
{
|
|
2261
|
+
return new Enumerator(_token);
|
|
2262
|
+
}
|
|
2263
|
+
|
|
2264
|
+
IEnumerator<
|
|
2265
|
+
KeyValuePair<MessageRegistrationHandle, MessageRegistrationMetadata>
|
|
2266
|
+
> IEnumerable<
|
|
2267
|
+
KeyValuePair<MessageRegistrationHandle, MessageRegistrationMetadata>
|
|
2268
|
+
>.GetEnumerator()
|
|
2269
|
+
{
|
|
2270
|
+
return GetEnumerator();
|
|
2271
|
+
}
|
|
2272
|
+
|
|
2273
|
+
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
|
|
2274
|
+
{
|
|
2275
|
+
return GetEnumerator();
|
|
2276
|
+
}
|
|
2277
|
+
|
|
2278
|
+
internal struct Enumerator
|
|
2279
|
+
: IEnumerator<KeyValuePair<MessageRegistrationHandle, MessageRegistrationMetadata>>
|
|
2280
|
+
{
|
|
2281
|
+
private readonly MessageRegistrationToken _token;
|
|
2282
|
+
private int _next;
|
|
2283
|
+
private KeyValuePair<
|
|
2284
|
+
MessageRegistrationHandle,
|
|
2285
|
+
MessageRegistrationMetadata
|
|
2286
|
+
> _current;
|
|
2287
|
+
|
|
2288
|
+
internal Enumerator(MessageRegistrationToken token)
|
|
2289
|
+
{
|
|
2290
|
+
_token = token;
|
|
2291
|
+
_next = token._registrationHead;
|
|
2292
|
+
_current = default;
|
|
2293
|
+
}
|
|
2294
|
+
|
|
2295
|
+
public KeyValuePair<
|
|
2296
|
+
MessageRegistrationHandle,
|
|
2297
|
+
MessageRegistrationMetadata
|
|
2298
|
+
> Current => _current;
|
|
2299
|
+
|
|
2300
|
+
object System.Collections.IEnumerator.Current => _current;
|
|
2301
|
+
|
|
2302
|
+
public bool MoveNext()
|
|
2303
|
+
{
|
|
2304
|
+
if (_next < 0)
|
|
2305
|
+
{
|
|
2306
|
+
return false;
|
|
2307
|
+
}
|
|
2308
|
+
|
|
2309
|
+
int slotIndex = _next;
|
|
2310
|
+
RegistrationSlot slot = _token._slots[slotIndex];
|
|
2311
|
+
_next = slot.Next;
|
|
2312
|
+
_current = new KeyValuePair<
|
|
2313
|
+
MessageRegistrationHandle,
|
|
2314
|
+
MessageRegistrationMetadata
|
|
2315
|
+
>(
|
|
2316
|
+
MessageRegistrationHandle.FromIdentity(slot.Id, slotIndex),
|
|
2317
|
+
slot.Registration.Metadata
|
|
2318
|
+
);
|
|
2319
|
+
return true;
|
|
2320
|
+
}
|
|
2321
|
+
|
|
2322
|
+
public void Reset()
|
|
2323
|
+
{
|
|
2324
|
+
_next = _token._registrationHead;
|
|
2325
|
+
_current = default;
|
|
2326
|
+
}
|
|
2327
|
+
|
|
2328
|
+
public void Dispose() { }
|
|
2329
|
+
}
|
|
2330
|
+
}
|
|
2331
|
+
|
|
2332
|
+
// Holds the live de-registration Actions for a single handle in the MULTI-de-registration
|
|
2333
|
+
// case (2+). The common case is EXACTLY ONE de-registration per handle (the existing
|
|
2334
|
+
// Registration object executes its embedded teardown state); that Registration is stored
|
|
2335
|
+
// INLINE as the slot value, so the common path allocates no
|
|
2336
|
+
// PendingDeregistration object at all (see AddDeregistration / InvokeDeregistration). This
|
|
2337
|
+
// holder is allocated only when a rare second de-registration accumulates on the same
|
|
2338
|
+
// handle -- a re-entrant retarget-recovery replay can stage one beyond the rollback
|
|
2339
|
+
// baseline -- at which point the inline Registration is promoted into this holder's head
|
|
2340
|
+
// and the second spills to a lazily-allocated overflow list. This stays a class (mutated in
|
|
2341
|
+
// place through the _deregistrations dictionary), so reference semantics and every
|
|
2342
|
+
// call site are unchanged; only the storage shape changed.
|
|
2343
|
+
//
|
|
2344
|
+
// Invariant: when Count > 0 the head lives in _hasHead/_head and is the LOGICAL
|
|
2345
|
+
// FIRST entry; any further entries follow in _overflow in insertion order. Add
|
|
2346
|
+
// appends to the logical tail; InvokeFrom invokes a contiguous logical tail
|
|
2347
|
+
// [startIndex..Count), removing each success and KEEPING each failure (retryable),
|
|
2348
|
+
// then promotes the first surviving overflow entry into the head slot if the head
|
|
2111
2349
|
// was consumed -- preserving the exact ordering, partial-failure, and
|
|
2112
2350
|
// rollback-baseline (startIndex) semantics the List<Action> form had.
|
|
2113
2351
|
private sealed class PendingDeregistration
|
|
@@ -2259,10 +2497,11 @@ namespace DxMessaging.Core
|
|
|
2259
2497
|
// user-accepted "unified object, accept the kind-switch" design -- NOT ~14
|
|
2260
2498
|
// subclasses). GlobalAcceptAllRegistration is non-generic (its sub-handlers
|
|
2261
2499
|
// are the fixed IMessage facades).
|
|
2262
|
-
private abstract class Registration
|
|
2500
|
+
private abstract class Registration : MessageHandler.HandlerDeregistration
|
|
2263
2501
|
{
|
|
2264
2502
|
protected readonly MessageRegistrationToken Token;
|
|
2265
2503
|
public MessageRegistrationHandle Handle;
|
|
2504
|
+
private IMessageBus _registeredMessageBus;
|
|
2266
2505
|
|
|
2267
2506
|
protected Registration(MessageRegistrationToken token)
|
|
2268
2507
|
{
|
|
@@ -2276,9 +2515,109 @@ namespace DxMessaging.Core
|
|
|
2276
2515
|
// the staging closure at call time -- the staging closure also read the
|
|
2277
2516
|
// field, not a snapshot).
|
|
2278
2517
|
public abstract MessageHandler.HandlerDeregistration Register();
|
|
2518
|
+
|
|
2519
|
+
public abstract MessageRegistrationMetadata Metadata { get; }
|
|
2520
|
+
|
|
2521
|
+
protected static MessageRegistrationType GetRegistrationType(RegistrationKind kind)
|
|
2522
|
+
{
|
|
2523
|
+
switch (kind)
|
|
2524
|
+
{
|
|
2525
|
+
case RegistrationKind.TargetedHandlerAction:
|
|
2526
|
+
case RegistrationKind.TargetedHandlerFast:
|
|
2527
|
+
return MessageRegistrationType.Targeted;
|
|
2528
|
+
case RegistrationKind.TargetedPostProcessorAction:
|
|
2529
|
+
case RegistrationKind.TargetedPostProcessorFast:
|
|
2530
|
+
return MessageRegistrationType.TargetedPostProcessor;
|
|
2531
|
+
case RegistrationKind.TargetedWithoutTargetingAction:
|
|
2532
|
+
case RegistrationKind.TargetedWithoutTargetingFast:
|
|
2533
|
+
return MessageRegistrationType.TargetedWithoutTargeting;
|
|
2534
|
+
case RegistrationKind.TargetedWithoutTargetingPostProcessorAction:
|
|
2535
|
+
case RegistrationKind.TargetedWithoutTargetingPostProcessorFast:
|
|
2536
|
+
return MessageRegistrationType.TargetedWithoutTargetingPostProcessor;
|
|
2537
|
+
case RegistrationKind.TargetedInterceptor:
|
|
2538
|
+
return MessageRegistrationType.TargetedInterceptor;
|
|
2539
|
+
case RegistrationKind.UntargetedHandlerAction:
|
|
2540
|
+
case RegistrationKind.UntargetedHandlerFast:
|
|
2541
|
+
return MessageRegistrationType.Untargeted;
|
|
2542
|
+
case RegistrationKind.UntargetedPostProcessorFast:
|
|
2543
|
+
return MessageRegistrationType.UntargetedPostProcessor;
|
|
2544
|
+
case RegistrationKind.UntargetedInterceptor:
|
|
2545
|
+
return MessageRegistrationType.UntargetedInterceptor;
|
|
2546
|
+
case RegistrationKind.BroadcastHandlerAction:
|
|
2547
|
+
case RegistrationKind.BroadcastHandlerFast:
|
|
2548
|
+
return MessageRegistrationType.Broadcast;
|
|
2549
|
+
case RegistrationKind.BroadcastPostProcessorAction:
|
|
2550
|
+
case RegistrationKind.BroadcastPostProcessorFast:
|
|
2551
|
+
return MessageRegistrationType.BroadcastPostProcessor;
|
|
2552
|
+
case RegistrationKind.BroadcastWithoutSourceAction:
|
|
2553
|
+
case RegistrationKind.BroadcastWithoutSourceFast:
|
|
2554
|
+
return MessageRegistrationType.BroadcastWithoutSource;
|
|
2555
|
+
case RegistrationKind.BroadcastWithoutSourcePostProcessorAction:
|
|
2556
|
+
case RegistrationKind.BroadcastWithoutSourcePostProcessorFast:
|
|
2557
|
+
return MessageRegistrationType.BroadcastWithoutSourcePostProcessor;
|
|
2558
|
+
case RegistrationKind.BroadcastInterceptor:
|
|
2559
|
+
return MessageRegistrationType.BroadcastInterceptor;
|
|
2560
|
+
case RegistrationKind.GlobalAcceptAllAction:
|
|
2561
|
+
case RegistrationKind.GlobalAcceptAllFast:
|
|
2562
|
+
return MessageRegistrationType.GlobalAcceptAll;
|
|
2563
|
+
default:
|
|
2564
|
+
return MessageRegistrationType.None;
|
|
2565
|
+
}
|
|
2566
|
+
}
|
|
2567
|
+
|
|
2568
|
+
protected IMessageBus ResolveRegistrationMessageBus()
|
|
2569
|
+
{
|
|
2570
|
+
IMessageBus messageBus = Token._messageBus;
|
|
2571
|
+
_registeredMessageBus = messageBus ?? Token._messageHandler?.DefaultMessageBus;
|
|
2572
|
+
return messageBus;
|
|
2573
|
+
}
|
|
2574
|
+
|
|
2575
|
+
protected void RecordDiagnosticEmission(IMessage message, InstanceId? context = null)
|
|
2576
|
+
{
|
|
2577
|
+
Token.RecordDiagnosticEmission(Handle, _registeredMessageBus, message, context);
|
|
2578
|
+
}
|
|
2579
|
+
}
|
|
2580
|
+
|
|
2581
|
+
private abstract class Registration<T> : Registration
|
|
2582
|
+
where T : IMessage
|
|
2583
|
+
{
|
|
2584
|
+
private MessageHandler.TypedHandler<T>.TypedHandlerDeregistrationState _typedDeregistration;
|
|
2585
|
+
private bool _hasInlineDeregistration;
|
|
2586
|
+
|
|
2587
|
+
protected Registration(MessageRegistrationToken token)
|
|
2588
|
+
: base(token) { }
|
|
2589
|
+
|
|
2590
|
+
protected MessageHandler.HandlerDeregistration StoreDeregistration(
|
|
2591
|
+
MessageHandler.TypedHandler<T>.TypedHandlerDeregistrationState deregistration
|
|
2592
|
+
)
|
|
2593
|
+
{
|
|
2594
|
+
if (_hasInlineDeregistration)
|
|
2595
|
+
{
|
|
2596
|
+
return deregistration;
|
|
2597
|
+
}
|
|
2598
|
+
|
|
2599
|
+
_typedDeregistration = deregistration;
|
|
2600
|
+
_hasInlineDeregistration = true;
|
|
2601
|
+
return this;
|
|
2602
|
+
}
|
|
2603
|
+
|
|
2604
|
+
internal override void Deregister()
|
|
2605
|
+
{
|
|
2606
|
+
if (!_hasInlineDeregistration)
|
|
2607
|
+
{
|
|
2608
|
+
return;
|
|
2609
|
+
}
|
|
2610
|
+
|
|
2611
|
+
_typedDeregistration.Deregister();
|
|
2612
|
+
|
|
2613
|
+
// Clear only after successful teardown. If a custom bus throws, this
|
|
2614
|
+
// registration remains the retryable inline action and any recovery
|
|
2615
|
+
// registration spills into an independent compatibility wrapper.
|
|
2616
|
+
_hasInlineDeregistration = false;
|
|
2617
|
+
}
|
|
2279
2618
|
}
|
|
2280
2619
|
|
|
2281
|
-
private sealed class TargetedRegistration<T> : Registration
|
|
2620
|
+
private sealed class TargetedRegistration<T> : Registration<T>
|
|
2282
2621
|
where T : ITargetedMessage
|
|
2283
2622
|
{
|
|
2284
2623
|
private readonly RegistrationKind _kind;
|
|
@@ -2310,85 +2649,108 @@ namespace DxMessaging.Core
|
|
|
2310
2649
|
_priority = priority;
|
|
2311
2650
|
}
|
|
2312
2651
|
|
|
2652
|
+
public override MessageRegistrationMetadata Metadata =>
|
|
2653
|
+
new MessageRegistrationMetadata(
|
|
2654
|
+
_kind == RegistrationKind.TargetedHandlerAction
|
|
2655
|
+
|| _kind == RegistrationKind.TargetedHandlerFast
|
|
2656
|
+
|| _kind == RegistrationKind.TargetedPostProcessorAction
|
|
2657
|
+
|| _kind == RegistrationKind.TargetedPostProcessorFast
|
|
2658
|
+
? _context
|
|
2659
|
+
: (InstanceId?)null,
|
|
2660
|
+
typeof(T),
|
|
2661
|
+
GetRegistrationType(_kind),
|
|
2662
|
+
_priority
|
|
2663
|
+
);
|
|
2664
|
+
|
|
2313
2665
|
public override MessageHandler.HandlerDeregistration Register()
|
|
2314
2666
|
{
|
|
2315
2667
|
MessageHandler messageHandler = Token._messageHandler;
|
|
2316
|
-
IMessageBus messageBus =
|
|
2668
|
+
IMessageBus messageBus = ResolveRegistrationMessageBus();
|
|
2317
2669
|
switch (_kind)
|
|
2318
2670
|
{
|
|
2319
2671
|
case RegistrationKind.TargetedHandlerAction:
|
|
2320
2672
|
_scalarAction = (Action<T>)_userHandler;
|
|
2321
|
-
return
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2673
|
+
return StoreDeregistration(
|
|
2674
|
+
messageHandler.RegisterTargetedMessageHandler(
|
|
2675
|
+
_context,
|
|
2676
|
+
_scalarAction,
|
|
2677
|
+
AugmentedScalarAction,
|
|
2678
|
+
priority: _priority,
|
|
2679
|
+
messageBus: messageBus
|
|
2680
|
+
)
|
|
2327
2681
|
);
|
|
2328
2682
|
case RegistrationKind.TargetedHandlerFast:
|
|
2329
2683
|
_scalarFast = (MessageHandler.FastHandler<T>)_userHandler;
|
|
2330
|
-
return
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2684
|
+
return StoreDeregistration(
|
|
2685
|
+
messageHandler.RegisterTargetedMessageHandler(
|
|
2686
|
+
_context,
|
|
2687
|
+
_scalarFast,
|
|
2688
|
+
AugmentedScalarFast,
|
|
2689
|
+
priority: _priority,
|
|
2690
|
+
messageBus: messageBus
|
|
2691
|
+
)
|
|
2336
2692
|
);
|
|
2337
2693
|
case RegistrationKind.TargetedPostProcessorAction:
|
|
2338
2694
|
_scalarAction = (Action<T>)_userHandler;
|
|
2339
|
-
return
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2695
|
+
return StoreDeregistration(
|
|
2696
|
+
messageHandler.RegisterTargetedPostProcessor(
|
|
2697
|
+
_context,
|
|
2698
|
+
_scalarAction,
|
|
2699
|
+
AugmentedScalarAction,
|
|
2700
|
+
_priority,
|
|
2701
|
+
messageBus
|
|
2702
|
+
)
|
|
2345
2703
|
);
|
|
2346
2704
|
case RegistrationKind.TargetedPostProcessorFast:
|
|
2347
2705
|
_scalarFast = (MessageHandler.FastHandler<T>)_userHandler;
|
|
2348
|
-
return
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2706
|
+
return StoreDeregistration(
|
|
2707
|
+
messageHandler.RegisterTargetedPostProcessor(
|
|
2708
|
+
_context,
|
|
2709
|
+
_scalarFast,
|
|
2710
|
+
AugmentedScalarFast,
|
|
2711
|
+
_priority,
|
|
2712
|
+
messageBus
|
|
2713
|
+
)
|
|
2354
2714
|
);
|
|
2355
2715
|
case RegistrationKind.TargetedWithoutTargetingAction:
|
|
2356
2716
|
_contextAction = (Action<InstanceId, T>)_userHandler;
|
|
2357
|
-
return
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2717
|
+
return StoreDeregistration(
|
|
2718
|
+
messageHandler.RegisterTargetedWithoutTargeting(
|
|
2719
|
+
_contextAction,
|
|
2720
|
+
AugmentedContextAction,
|
|
2721
|
+
priority: _priority,
|
|
2722
|
+
messageBus: messageBus
|
|
2723
|
+
)
|
|
2362
2724
|
);
|
|
2363
2725
|
case RegistrationKind.TargetedWithoutTargetingFast:
|
|
2364
2726
|
_contextFast = (MessageHandler.FastHandlerWithContext<T>)_userHandler;
|
|
2365
|
-
return
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2727
|
+
return StoreDeregistration(
|
|
2728
|
+
messageHandler.RegisterTargetedWithoutTargeting(
|
|
2729
|
+
_contextFast,
|
|
2730
|
+
AugmentedContextFast,
|
|
2731
|
+
priority: _priority,
|
|
2732
|
+
messageBus: messageBus
|
|
2733
|
+
)
|
|
2370
2734
|
);
|
|
2371
2735
|
case RegistrationKind.TargetedWithoutTargetingPostProcessorAction:
|
|
2372
2736
|
_contextAction = (Action<InstanceId, T>)_userHandler;
|
|
2373
|
-
return
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2737
|
+
return StoreDeregistration(
|
|
2738
|
+
messageHandler.RegisterTargetedWithoutTargetingPostProcessor(
|
|
2739
|
+
_contextAction,
|
|
2740
|
+
AugmentedContextAction,
|
|
2741
|
+
_priority,
|
|
2742
|
+
messageBus
|
|
2743
|
+
)
|
|
2378
2744
|
);
|
|
2379
2745
|
case RegistrationKind.TargetedWithoutTargetingPostProcessorFast:
|
|
2380
2746
|
_contextFast = (MessageHandler.FastHandlerWithContext<T>)_userHandler;
|
|
2381
|
-
return
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
return messageHandler.RegisterTargetedInterceptor(
|
|
2389
|
-
(IMessageBus.TargetedInterceptor<T>)_userHandler,
|
|
2390
|
-
priority: _priority,
|
|
2391
|
-
messageBus: messageBus
|
|
2747
|
+
return StoreDeregistration(
|
|
2748
|
+
messageHandler.RegisterTargetedWithoutTargetingPostProcessor(
|
|
2749
|
+
_contextFast,
|
|
2750
|
+
AugmentedContextFast,
|
|
2751
|
+
_priority,
|
|
2752
|
+
messageBus
|
|
2753
|
+
)
|
|
2392
2754
|
);
|
|
2393
2755
|
default:
|
|
2394
2756
|
throw new InvalidOperationException(
|
|
@@ -2406,8 +2768,7 @@ namespace DxMessaging.Core
|
|
|
2406
2768
|
_scalarAction(message);
|
|
2407
2769
|
if (Token._diagnosticMode)
|
|
2408
2770
|
{
|
|
2409
|
-
|
|
2410
|
-
Token._emissionBuffer.Add(new MessageEmissionData(message, _context));
|
|
2771
|
+
RecordDiagnosticEmission(message, _context);
|
|
2411
2772
|
}
|
|
2412
2773
|
}
|
|
2413
2774
|
|
|
@@ -2416,8 +2777,7 @@ namespace DxMessaging.Core
|
|
|
2416
2777
|
_scalarFast(ref message);
|
|
2417
2778
|
if (Token._diagnosticMode)
|
|
2418
2779
|
{
|
|
2419
|
-
|
|
2420
|
-
Token._emissionBuffer.Add(new MessageEmissionData(message, _context));
|
|
2780
|
+
RecordDiagnosticEmission(message, _context);
|
|
2421
2781
|
}
|
|
2422
2782
|
}
|
|
2423
2783
|
|
|
@@ -2429,8 +2789,7 @@ namespace DxMessaging.Core
|
|
|
2429
2789
|
_contextAction(target, message);
|
|
2430
2790
|
if (Token._diagnosticMode)
|
|
2431
2791
|
{
|
|
2432
|
-
|
|
2433
|
-
Token._emissionBuffer.Add(new MessageEmissionData(message, target));
|
|
2792
|
+
RecordDiagnosticEmission(message, target);
|
|
2434
2793
|
}
|
|
2435
2794
|
}
|
|
2436
2795
|
|
|
@@ -2439,13 +2798,12 @@ namespace DxMessaging.Core
|
|
|
2439
2798
|
_contextFast(ref target, ref message);
|
|
2440
2799
|
if (Token._diagnosticMode)
|
|
2441
2800
|
{
|
|
2442
|
-
|
|
2443
|
-
Token._emissionBuffer.Add(new MessageEmissionData(message, target));
|
|
2801
|
+
RecordDiagnosticEmission(message, target);
|
|
2444
2802
|
}
|
|
2445
2803
|
}
|
|
2446
2804
|
}
|
|
2447
2805
|
|
|
2448
|
-
private sealed class UntargetedRegistration<T> : Registration
|
|
2806
|
+
private sealed class UntargetedRegistration<T> : Registration<T>
|
|
2449
2807
|
where T : IUntargetedMessage
|
|
2450
2808
|
{
|
|
2451
2809
|
private readonly RegistrationKind _kind;
|
|
@@ -2471,41 +2829,49 @@ namespace DxMessaging.Core
|
|
|
2471
2829
|
_priority = priority;
|
|
2472
2830
|
}
|
|
2473
2831
|
|
|
2832
|
+
public override MessageRegistrationMetadata Metadata =>
|
|
2833
|
+
new MessageRegistrationMetadata(
|
|
2834
|
+
null,
|
|
2835
|
+
typeof(T),
|
|
2836
|
+
GetRegistrationType(_kind),
|
|
2837
|
+
_priority
|
|
2838
|
+
);
|
|
2839
|
+
|
|
2474
2840
|
public override MessageHandler.HandlerDeregistration Register()
|
|
2475
2841
|
{
|
|
2476
2842
|
MessageHandler messageHandler = Token._messageHandler;
|
|
2477
|
-
IMessageBus messageBus =
|
|
2843
|
+
IMessageBus messageBus = ResolveRegistrationMessageBus();
|
|
2478
2844
|
switch (_kind)
|
|
2479
2845
|
{
|
|
2480
2846
|
case RegistrationKind.UntargetedHandlerAction:
|
|
2481
2847
|
_scalarAction = (Action<T>)_userHandler;
|
|
2482
|
-
return
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2848
|
+
return StoreDeregistration(
|
|
2849
|
+
messageHandler.RegisterUntargetedMessageHandler(
|
|
2850
|
+
_scalarAction,
|
|
2851
|
+
AugmentedScalarAction,
|
|
2852
|
+
priority: _priority,
|
|
2853
|
+
messageBus: messageBus
|
|
2854
|
+
)
|
|
2487
2855
|
);
|
|
2488
2856
|
case RegistrationKind.UntargetedHandlerFast:
|
|
2489
2857
|
_scalarFast = (MessageHandler.FastHandler<T>)_userHandler;
|
|
2490
|
-
return
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2858
|
+
return StoreDeregistration(
|
|
2859
|
+
messageHandler.RegisterUntargetedMessageHandler(
|
|
2860
|
+
_scalarFast,
|
|
2861
|
+
AugmentedScalarFast,
|
|
2862
|
+
priority: _priority,
|
|
2863
|
+
messageBus: messageBus
|
|
2864
|
+
)
|
|
2495
2865
|
);
|
|
2496
2866
|
case RegistrationKind.UntargetedPostProcessorFast:
|
|
2497
2867
|
_scalarFast = (MessageHandler.FastHandler<T>)_userHandler;
|
|
2498
|
-
return
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
return messageHandler.RegisterUntargetedInterceptor(
|
|
2506
|
-
(IMessageBus.UntargetedInterceptor<T>)_userHandler,
|
|
2507
|
-
priority: _priority,
|
|
2508
|
-
messageBus: messageBus
|
|
2868
|
+
return StoreDeregistration(
|
|
2869
|
+
messageHandler.RegisterUntargetedPostProcessor(
|
|
2870
|
+
_scalarFast,
|
|
2871
|
+
AugmentedScalarFast,
|
|
2872
|
+
_priority,
|
|
2873
|
+
messageBus
|
|
2874
|
+
)
|
|
2509
2875
|
);
|
|
2510
2876
|
default:
|
|
2511
2877
|
throw new InvalidOperationException(
|
|
@@ -2521,8 +2887,7 @@ namespace DxMessaging.Core
|
|
|
2521
2887
|
_scalarAction(message);
|
|
2522
2888
|
if (Token._diagnosticMode)
|
|
2523
2889
|
{
|
|
2524
|
-
|
|
2525
|
-
Token._emissionBuffer.Add(new MessageEmissionData(message));
|
|
2890
|
+
RecordDiagnosticEmission(message);
|
|
2526
2891
|
}
|
|
2527
2892
|
}
|
|
2528
2893
|
|
|
@@ -2531,13 +2896,12 @@ namespace DxMessaging.Core
|
|
|
2531
2896
|
_scalarFast(ref message);
|
|
2532
2897
|
if (Token._diagnosticMode)
|
|
2533
2898
|
{
|
|
2534
|
-
|
|
2535
|
-
Token._emissionBuffer.Add(new MessageEmissionData(message));
|
|
2899
|
+
RecordDiagnosticEmission(message);
|
|
2536
2900
|
}
|
|
2537
2901
|
}
|
|
2538
2902
|
}
|
|
2539
2903
|
|
|
2540
|
-
private sealed class BroadcastRegistration<T> : Registration
|
|
2904
|
+
private sealed class BroadcastRegistration<T> : Registration<T>
|
|
2541
2905
|
where T : IBroadcastMessage
|
|
2542
2906
|
{
|
|
2543
2907
|
private readonly RegistrationKind _kind;
|
|
@@ -2568,85 +2932,108 @@ namespace DxMessaging.Core
|
|
|
2568
2932
|
_priority = priority;
|
|
2569
2933
|
}
|
|
2570
2934
|
|
|
2935
|
+
public override MessageRegistrationMetadata Metadata =>
|
|
2936
|
+
new MessageRegistrationMetadata(
|
|
2937
|
+
_kind == RegistrationKind.BroadcastHandlerAction
|
|
2938
|
+
|| _kind == RegistrationKind.BroadcastHandlerFast
|
|
2939
|
+
|| _kind == RegistrationKind.BroadcastPostProcessorAction
|
|
2940
|
+
|| _kind == RegistrationKind.BroadcastPostProcessorFast
|
|
2941
|
+
? _context
|
|
2942
|
+
: (InstanceId?)null,
|
|
2943
|
+
typeof(T),
|
|
2944
|
+
GetRegistrationType(_kind),
|
|
2945
|
+
_priority
|
|
2946
|
+
);
|
|
2947
|
+
|
|
2571
2948
|
public override MessageHandler.HandlerDeregistration Register()
|
|
2572
2949
|
{
|
|
2573
2950
|
MessageHandler messageHandler = Token._messageHandler;
|
|
2574
|
-
IMessageBus messageBus =
|
|
2951
|
+
IMessageBus messageBus = ResolveRegistrationMessageBus();
|
|
2575
2952
|
switch (_kind)
|
|
2576
2953
|
{
|
|
2577
2954
|
case RegistrationKind.BroadcastHandlerAction:
|
|
2578
2955
|
_scalarAction = (Action<T>)_userHandler;
|
|
2579
|
-
return
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2956
|
+
return StoreDeregistration(
|
|
2957
|
+
messageHandler.RegisterSourcedBroadcastMessageHandler(
|
|
2958
|
+
_context,
|
|
2959
|
+
_scalarAction,
|
|
2960
|
+
AugmentedScalarAction,
|
|
2961
|
+
priority: _priority,
|
|
2962
|
+
messageBus: messageBus
|
|
2963
|
+
)
|
|
2585
2964
|
);
|
|
2586
2965
|
case RegistrationKind.BroadcastHandlerFast:
|
|
2587
2966
|
_scalarFast = (MessageHandler.FastHandler<T>)_userHandler;
|
|
2588
|
-
return
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2967
|
+
return StoreDeregistration(
|
|
2968
|
+
messageHandler.RegisterSourcedBroadcastMessageHandler(
|
|
2969
|
+
_context,
|
|
2970
|
+
_scalarFast,
|
|
2971
|
+
AugmentedScalarFast,
|
|
2972
|
+
priority: _priority,
|
|
2973
|
+
messageBus: messageBus
|
|
2974
|
+
)
|
|
2594
2975
|
);
|
|
2595
2976
|
case RegistrationKind.BroadcastPostProcessorAction:
|
|
2596
2977
|
_scalarAction = (Action<T>)_userHandler;
|
|
2597
|
-
return
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2978
|
+
return StoreDeregistration(
|
|
2979
|
+
messageHandler.RegisterSourcedBroadcastPostProcessor(
|
|
2980
|
+
_context,
|
|
2981
|
+
_scalarAction,
|
|
2982
|
+
AugmentedScalarAction,
|
|
2983
|
+
_priority,
|
|
2984
|
+
messageBus
|
|
2985
|
+
)
|
|
2603
2986
|
);
|
|
2604
2987
|
case RegistrationKind.BroadcastPostProcessorFast:
|
|
2605
2988
|
_scalarFast = (MessageHandler.FastHandler<T>)_userHandler;
|
|
2606
|
-
return
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2989
|
+
return StoreDeregistration(
|
|
2990
|
+
messageHandler.RegisterSourcedBroadcastPostProcessor(
|
|
2991
|
+
_context,
|
|
2992
|
+
_scalarFast,
|
|
2993
|
+
AugmentedScalarFast,
|
|
2994
|
+
_priority,
|
|
2995
|
+
messageBus
|
|
2996
|
+
)
|
|
2612
2997
|
);
|
|
2613
2998
|
case RegistrationKind.BroadcastWithoutSourceAction:
|
|
2614
2999
|
_contextAction = (Action<InstanceId, T>)_userHandler;
|
|
2615
|
-
return
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
3000
|
+
return StoreDeregistration(
|
|
3001
|
+
messageHandler.RegisterSourcedBroadcastWithoutSource(
|
|
3002
|
+
_contextAction,
|
|
3003
|
+
AugmentedContextAction,
|
|
3004
|
+
priority: _priority,
|
|
3005
|
+
messageBus: messageBus
|
|
3006
|
+
)
|
|
2620
3007
|
);
|
|
2621
3008
|
case RegistrationKind.BroadcastWithoutSourceFast:
|
|
2622
3009
|
_contextFast = (MessageHandler.FastHandlerWithContext<T>)_userHandler;
|
|
2623
|
-
return
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
3010
|
+
return StoreDeregistration(
|
|
3011
|
+
messageHandler.RegisterSourcedBroadcastWithoutSource(
|
|
3012
|
+
_contextFast,
|
|
3013
|
+
AugmentedContextFast,
|
|
3014
|
+
priority: _priority,
|
|
3015
|
+
messageBus: messageBus
|
|
3016
|
+
)
|
|
2628
3017
|
);
|
|
2629
3018
|
case RegistrationKind.BroadcastWithoutSourcePostProcessorAction:
|
|
2630
3019
|
_contextAction = (Action<InstanceId, T>)_userHandler;
|
|
2631
|
-
return
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
|
|
3020
|
+
return StoreDeregistration(
|
|
3021
|
+
messageHandler.RegisterSourcedBroadcastWithoutSourcePostProcessor(
|
|
3022
|
+
_contextAction,
|
|
3023
|
+
AugmentedContextAction,
|
|
3024
|
+
priority: _priority,
|
|
3025
|
+
messageBus
|
|
3026
|
+
)
|
|
2636
3027
|
);
|
|
2637
3028
|
case RegistrationKind.BroadcastWithoutSourcePostProcessorFast:
|
|
2638
3029
|
_contextFast = (MessageHandler.FastHandlerWithContext<T>)_userHandler;
|
|
2639
|
-
return
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
return messageHandler.RegisterBroadcastInterceptor(
|
|
2647
|
-
(IMessageBus.BroadcastInterceptor<T>)_userHandler,
|
|
2648
|
-
priority: _priority,
|
|
2649
|
-
messageBus: messageBus
|
|
3030
|
+
return StoreDeregistration(
|
|
3031
|
+
messageHandler.RegisterSourcedBroadcastWithoutSourcePostProcessor(
|
|
3032
|
+
_contextFast,
|
|
3033
|
+
AugmentedContextFast,
|
|
3034
|
+
priority: _priority,
|
|
3035
|
+
messageBus
|
|
3036
|
+
)
|
|
2650
3037
|
);
|
|
2651
3038
|
default:
|
|
2652
3039
|
throw new InvalidOperationException(
|
|
@@ -2662,8 +3049,7 @@ namespace DxMessaging.Core
|
|
|
2662
3049
|
_scalarAction(message);
|
|
2663
3050
|
if (Token._diagnosticMode)
|
|
2664
3051
|
{
|
|
2665
|
-
|
|
2666
|
-
Token._emissionBuffer.Add(new MessageEmissionData(message, _context));
|
|
3052
|
+
RecordDiagnosticEmission(message, _context);
|
|
2667
3053
|
}
|
|
2668
3054
|
}
|
|
2669
3055
|
|
|
@@ -2672,8 +3058,7 @@ namespace DxMessaging.Core
|
|
|
2672
3058
|
_scalarFast(ref message);
|
|
2673
3059
|
if (Token._diagnosticMode)
|
|
2674
3060
|
{
|
|
2675
|
-
|
|
2676
|
-
Token._emissionBuffer.Add(new MessageEmissionData(message, _context));
|
|
3061
|
+
RecordDiagnosticEmission(message, _context);
|
|
2677
3062
|
}
|
|
2678
3063
|
}
|
|
2679
3064
|
|
|
@@ -2685,8 +3070,7 @@ namespace DxMessaging.Core
|
|
|
2685
3070
|
_contextAction(source, message);
|
|
2686
3071
|
if (Token._diagnosticMode)
|
|
2687
3072
|
{
|
|
2688
|
-
|
|
2689
|
-
Token._emissionBuffer.Add(new MessageEmissionData(message, source));
|
|
3073
|
+
RecordDiagnosticEmission(message, source);
|
|
2690
3074
|
}
|
|
2691
3075
|
}
|
|
2692
3076
|
|
|
@@ -2695,9 +3079,152 @@ namespace DxMessaging.Core
|
|
|
2695
3079
|
_contextFast(ref source, ref message);
|
|
2696
3080
|
if (Token._diagnosticMode)
|
|
2697
3081
|
{
|
|
2698
|
-
|
|
2699
|
-
|
|
3082
|
+
RecordDiagnosticEmission(message, source);
|
|
3083
|
+
}
|
|
3084
|
+
}
|
|
3085
|
+
}
|
|
3086
|
+
|
|
3087
|
+
private abstract class InterceptorRegistration<T> : Registration
|
|
3088
|
+
where T : IMessage
|
|
3089
|
+
{
|
|
3090
|
+
protected readonly int Priority;
|
|
3091
|
+
private MessageHandler.InterceptorDeregistrationState<T> _deregistration;
|
|
3092
|
+
private bool _hasInlineDeregistration;
|
|
3093
|
+
|
|
3094
|
+
protected InterceptorRegistration(MessageRegistrationToken token, int priority)
|
|
3095
|
+
: base(token)
|
|
3096
|
+
{
|
|
3097
|
+
Priority = priority;
|
|
3098
|
+
}
|
|
3099
|
+
|
|
3100
|
+
protected MessageHandler.HandlerDeregistration StoreDeregistration(
|
|
3101
|
+
MessageHandler.InterceptorDeregistrationState<T> deregistration
|
|
3102
|
+
)
|
|
3103
|
+
{
|
|
3104
|
+
if (_hasInlineDeregistration)
|
|
3105
|
+
{
|
|
3106
|
+
return deregistration;
|
|
3107
|
+
}
|
|
3108
|
+
|
|
3109
|
+
_deregistration = deregistration;
|
|
3110
|
+
_hasInlineDeregistration = true;
|
|
3111
|
+
return this;
|
|
3112
|
+
}
|
|
3113
|
+
|
|
3114
|
+
internal override void Deregister()
|
|
3115
|
+
{
|
|
3116
|
+
if (!_hasInlineDeregistration)
|
|
3117
|
+
{
|
|
3118
|
+
return;
|
|
2700
3119
|
}
|
|
3120
|
+
|
|
3121
|
+
_deregistration.Deregister();
|
|
3122
|
+
_hasInlineDeregistration = false;
|
|
3123
|
+
}
|
|
3124
|
+
}
|
|
3125
|
+
|
|
3126
|
+
private sealed class UntargetedInterceptorRegistration<T> : InterceptorRegistration<T>
|
|
3127
|
+
where T : IUntargetedMessage
|
|
3128
|
+
{
|
|
3129
|
+
private readonly IMessageBus.UntargetedInterceptor<T> _interceptor;
|
|
3130
|
+
|
|
3131
|
+
internal UntargetedInterceptorRegistration(
|
|
3132
|
+
MessageRegistrationToken token,
|
|
3133
|
+
IMessageBus.UntargetedInterceptor<T> interceptor,
|
|
3134
|
+
int priority
|
|
3135
|
+
)
|
|
3136
|
+
: base(token, priority)
|
|
3137
|
+
{
|
|
3138
|
+
_interceptor = interceptor;
|
|
3139
|
+
}
|
|
3140
|
+
|
|
3141
|
+
public override MessageRegistrationMetadata Metadata =>
|
|
3142
|
+
new MessageRegistrationMetadata(
|
|
3143
|
+
null,
|
|
3144
|
+
typeof(T),
|
|
3145
|
+
MessageRegistrationType.UntargetedInterceptor,
|
|
3146
|
+
Priority
|
|
3147
|
+
);
|
|
3148
|
+
|
|
3149
|
+
public override MessageHandler.HandlerDeregistration Register()
|
|
3150
|
+
{
|
|
3151
|
+
return StoreDeregistration(
|
|
3152
|
+
Token._messageHandler.RegisterUntargetedInterceptor(
|
|
3153
|
+
_interceptor,
|
|
3154
|
+
Priority,
|
|
3155
|
+
ResolveRegistrationMessageBus()
|
|
3156
|
+
)
|
|
3157
|
+
);
|
|
3158
|
+
}
|
|
3159
|
+
}
|
|
3160
|
+
|
|
3161
|
+
private sealed class TargetedInterceptorRegistration<T> : InterceptorRegistration<T>
|
|
3162
|
+
where T : ITargetedMessage
|
|
3163
|
+
{
|
|
3164
|
+
private readonly IMessageBus.TargetedInterceptor<T> _interceptor;
|
|
3165
|
+
|
|
3166
|
+
internal TargetedInterceptorRegistration(
|
|
3167
|
+
MessageRegistrationToken token,
|
|
3168
|
+
IMessageBus.TargetedInterceptor<T> interceptor,
|
|
3169
|
+
int priority
|
|
3170
|
+
)
|
|
3171
|
+
: base(token, priority)
|
|
3172
|
+
{
|
|
3173
|
+
_interceptor = interceptor;
|
|
3174
|
+
}
|
|
3175
|
+
|
|
3176
|
+
public override MessageRegistrationMetadata Metadata =>
|
|
3177
|
+
new MessageRegistrationMetadata(
|
|
3178
|
+
null,
|
|
3179
|
+
typeof(T),
|
|
3180
|
+
MessageRegistrationType.TargetedInterceptor,
|
|
3181
|
+
Priority
|
|
3182
|
+
);
|
|
3183
|
+
|
|
3184
|
+
public override MessageHandler.HandlerDeregistration Register()
|
|
3185
|
+
{
|
|
3186
|
+
return StoreDeregistration(
|
|
3187
|
+
Token._messageHandler.RegisterTargetedInterceptor(
|
|
3188
|
+
_interceptor,
|
|
3189
|
+
Priority,
|
|
3190
|
+
ResolveRegistrationMessageBus()
|
|
3191
|
+
)
|
|
3192
|
+
);
|
|
3193
|
+
}
|
|
3194
|
+
}
|
|
3195
|
+
|
|
3196
|
+
private sealed class BroadcastInterceptorRegistration<T> : InterceptorRegistration<T>
|
|
3197
|
+
where T : IBroadcastMessage
|
|
3198
|
+
{
|
|
3199
|
+
private readonly IMessageBus.BroadcastInterceptor<T> _interceptor;
|
|
3200
|
+
|
|
3201
|
+
internal BroadcastInterceptorRegistration(
|
|
3202
|
+
MessageRegistrationToken token,
|
|
3203
|
+
IMessageBus.BroadcastInterceptor<T> interceptor,
|
|
3204
|
+
int priority
|
|
3205
|
+
)
|
|
3206
|
+
: base(token, priority)
|
|
3207
|
+
{
|
|
3208
|
+
_interceptor = interceptor;
|
|
3209
|
+
}
|
|
3210
|
+
|
|
3211
|
+
public override MessageRegistrationMetadata Metadata =>
|
|
3212
|
+
new MessageRegistrationMetadata(
|
|
3213
|
+
null,
|
|
3214
|
+
typeof(T),
|
|
3215
|
+
MessageRegistrationType.BroadcastInterceptor,
|
|
3216
|
+
Priority
|
|
3217
|
+
);
|
|
3218
|
+
|
|
3219
|
+
public override MessageHandler.HandlerDeregistration Register()
|
|
3220
|
+
{
|
|
3221
|
+
return StoreDeregistration(
|
|
3222
|
+
Token._messageHandler.RegisterBroadcastInterceptor(
|
|
3223
|
+
_interceptor,
|
|
3224
|
+
Priority,
|
|
3225
|
+
ResolveRegistrationMessageBus()
|
|
3226
|
+
)
|
|
3227
|
+
);
|
|
2701
3228
|
}
|
|
2702
3229
|
}
|
|
2703
3230
|
|
|
@@ -2720,6 +3247,16 @@ namespace DxMessaging.Core
|
|
|
2720
3247
|
private readonly MessageHandler.FastHandler<IUntargetedMessage> _untargetedFast;
|
|
2721
3248
|
private readonly MessageHandler.FastHandlerWithContext<ITargetedMessage> _targetedFast;
|
|
2722
3249
|
private readonly MessageHandler.FastHandlerWithContext<IBroadcastMessage> _broadcastFast;
|
|
3250
|
+
private MessageHandler.GlobalAcceptAllDeregistrationState _deregistration;
|
|
3251
|
+
private bool _hasInlineDeregistration;
|
|
3252
|
+
|
|
3253
|
+
public override MessageRegistrationMetadata Metadata =>
|
|
3254
|
+
new MessageRegistrationMetadata(
|
|
3255
|
+
null,
|
|
3256
|
+
typeof(IMessage),
|
|
3257
|
+
MessageRegistrationType.GlobalAcceptAll,
|
|
3258
|
+
0
|
|
3259
|
+
);
|
|
2723
3260
|
|
|
2724
3261
|
internal GlobalAcceptAllRegistration(
|
|
2725
3262
|
MessageRegistrationToken token,
|
|
@@ -2752,38 +3289,66 @@ namespace DxMessaging.Core
|
|
|
2752
3289
|
public override MessageHandler.HandlerDeregistration Register()
|
|
2753
3290
|
{
|
|
2754
3291
|
MessageHandler messageHandler = Token._messageHandler;
|
|
2755
|
-
IMessageBus messageBus =
|
|
3292
|
+
IMessageBus messageBus = ResolveRegistrationMessageBus();
|
|
2756
3293
|
if (_kind == RegistrationKind.GlobalAcceptAllAction)
|
|
2757
3294
|
{
|
|
2758
|
-
return
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
|
|
3295
|
+
return StoreDeregistration(
|
|
3296
|
+
messageHandler.RegisterGlobalAcceptAll(
|
|
3297
|
+
_untargetedAction,
|
|
3298
|
+
AugmentedUntargetedAction,
|
|
3299
|
+
_targetedAction,
|
|
3300
|
+
AugmentedTargetedAction,
|
|
3301
|
+
_broadcastAction,
|
|
3302
|
+
AugmentedBroadcastAction,
|
|
3303
|
+
messageBus
|
|
3304
|
+
)
|
|
2766
3305
|
);
|
|
2767
3306
|
}
|
|
2768
3307
|
|
|
2769
|
-
return
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
3308
|
+
return StoreDeregistration(
|
|
3309
|
+
messageHandler.RegisterGlobalAcceptAll(
|
|
3310
|
+
_untargetedFast,
|
|
3311
|
+
AugmentedUntargetedFast,
|
|
3312
|
+
_targetedFast,
|
|
3313
|
+
AugmentedTargetedFast,
|
|
3314
|
+
_broadcastFast,
|
|
3315
|
+
AugmentedBroadcastFast,
|
|
3316
|
+
messageBus
|
|
3317
|
+
)
|
|
2777
3318
|
);
|
|
2778
3319
|
}
|
|
2779
3320
|
|
|
3321
|
+
internal override void Deregister()
|
|
3322
|
+
{
|
|
3323
|
+
if (!_hasInlineDeregistration)
|
|
3324
|
+
{
|
|
3325
|
+
return;
|
|
3326
|
+
}
|
|
3327
|
+
|
|
3328
|
+
_deregistration.Deregister();
|
|
3329
|
+
_hasInlineDeregistration = false;
|
|
3330
|
+
}
|
|
3331
|
+
|
|
3332
|
+
private MessageHandler.HandlerDeregistration StoreDeregistration(
|
|
3333
|
+
MessageHandler.GlobalAcceptAllDeregistrationState deregistration
|
|
3334
|
+
)
|
|
3335
|
+
{
|
|
3336
|
+
if (_hasInlineDeregistration)
|
|
3337
|
+
{
|
|
3338
|
+
return deregistration;
|
|
3339
|
+
}
|
|
3340
|
+
|
|
3341
|
+
_deregistration = deregistration;
|
|
3342
|
+
_hasInlineDeregistration = true;
|
|
3343
|
+
return this;
|
|
3344
|
+
}
|
|
3345
|
+
|
|
2780
3346
|
private void AugmentedUntargetedAction(IUntargetedMessage message)
|
|
2781
3347
|
{
|
|
2782
3348
|
_untargetedAction(message);
|
|
2783
3349
|
if (Token._diagnosticMode)
|
|
2784
3350
|
{
|
|
2785
|
-
|
|
2786
|
-
Token._emissionBuffer.Add(new MessageEmissionData(message));
|
|
3351
|
+
RecordDiagnosticEmission(message);
|
|
2787
3352
|
}
|
|
2788
3353
|
}
|
|
2789
3354
|
|
|
@@ -2792,8 +3357,7 @@ namespace DxMessaging.Core
|
|
|
2792
3357
|
_targetedAction(target, message);
|
|
2793
3358
|
if (Token._diagnosticMode)
|
|
2794
3359
|
{
|
|
2795
|
-
|
|
2796
|
-
Token._emissionBuffer.Add(new MessageEmissionData(message, target));
|
|
3360
|
+
RecordDiagnosticEmission(message, target);
|
|
2797
3361
|
}
|
|
2798
3362
|
}
|
|
2799
3363
|
|
|
@@ -2802,8 +3366,7 @@ namespace DxMessaging.Core
|
|
|
2802
3366
|
_broadcastAction(source, message);
|
|
2803
3367
|
if (Token._diagnosticMode)
|
|
2804
3368
|
{
|
|
2805
|
-
|
|
2806
|
-
Token._emissionBuffer.Add(new MessageEmissionData(message, source));
|
|
3369
|
+
RecordDiagnosticEmission(message, source);
|
|
2807
3370
|
}
|
|
2808
3371
|
}
|
|
2809
3372
|
|
|
@@ -2812,8 +3375,7 @@ namespace DxMessaging.Core
|
|
|
2812
3375
|
_untargetedFast(ref message);
|
|
2813
3376
|
if (Token._diagnosticMode)
|
|
2814
3377
|
{
|
|
2815
|
-
|
|
2816
|
-
Token._emissionBuffer.Add(new MessageEmissionData(message));
|
|
3378
|
+
RecordDiagnosticEmission(message);
|
|
2817
3379
|
}
|
|
2818
3380
|
}
|
|
2819
3381
|
|
|
@@ -2822,8 +3384,7 @@ namespace DxMessaging.Core
|
|
|
2822
3384
|
_targetedFast(ref target, ref message);
|
|
2823
3385
|
if (Token._diagnosticMode)
|
|
2824
3386
|
{
|
|
2825
|
-
|
|
2826
|
-
Token._emissionBuffer.Add(new MessageEmissionData(message, target));
|
|
3387
|
+
RecordDiagnosticEmission(message, target);
|
|
2827
3388
|
}
|
|
2828
3389
|
}
|
|
2829
3390
|
|
|
@@ -2835,8 +3396,7 @@ namespace DxMessaging.Core
|
|
|
2835
3396
|
_broadcastFast(ref source, ref message);
|
|
2836
3397
|
if (Token._diagnosticMode)
|
|
2837
3398
|
{
|
|
2838
|
-
|
|
2839
|
-
Token._emissionBuffer.Add(new MessageEmissionData(message, source));
|
|
3399
|
+
RecordDiagnosticEmission(message, source);
|
|
2840
3400
|
}
|
|
2841
3401
|
}
|
|
2842
3402
|
}
|