com.wallstop-studios.dxmessaging 2.1.2 → 2.1.4
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/.github/workflows/dotnet-tests.yml +3 -3
- package/.github/workflows/prettier-autofix.yml +0 -7
- package/.pre-commit-config.yaml +8 -5
- package/AGENTS.md +12 -12
- package/CONTRIBUTING.md +8 -2
- package/Docs/Comparisons.md +5 -5
- package/Docs/InterceptorsAndOrdering.md +1 -1
- package/Docs/Performance.md +13 -13
- package/Docs/QuickReference.md +1 -1
- package/Docs/Reference.md +5 -5
- package/Editor/Analyzers/WallstopStudios.DxMessaging.SourceGenerators.dll +0 -0
- package/Editor/CustomEditors/MessagingComponentEditor.cs +3 -0
- package/Editor/DxMessagingEditorInitializer.cs +58 -1
- package/Editor/DxMessagingMenu.cs +38 -0
- package/Editor/DxMessagingMenu.cs.meta +11 -0
- package/Editor/DxMessagingSceneBuildProcessor.cs +81 -0
- package/Editor/DxMessagingSceneBuildProcessor.cs.meta +11 -0
- package/Editor/Settings/DxMessagingSettings.cs +37 -6
- package/Editor/Settings/DxMessagingSettingsProvider.cs +45 -7
- package/README.md +1 -1
- package/Runtime/Core/Attributes/DxOptionalParameterAttribute.cs +52 -0
- package/Runtime/Core/DataStructure/CyclicBuffer.cs +16 -0
- package/Runtime/Core/Diagnostics/MessageEmissionData.cs +1 -1
- package/Runtime/Core/Diagnostics/MessageRegistrationType.cs +62 -0
- package/Runtime/Core/DxMessagingStaticState.cs +108 -0
- package/Runtime/Core/DxMessagingStaticState.cs.meta +11 -0
- package/Runtime/Core/Extensions/IListExtensions.cs +24 -0
- package/Runtime/Core/Extensions/MessageBusExtensions.cs +142 -0
- package/Runtime/Core/Helper/MessageCache.cs +16 -0
- package/Runtime/Core/Helper/MessageHelperIndexer.cs +77 -0
- package/Runtime/Core/InstanceId.cs +86 -0
- package/Runtime/Core/MessageBus/DiagnosticsTarget.cs +31 -0
- package/Runtime/Core/MessageBus/DiagnosticsTarget.cs.meta +11 -0
- package/Runtime/Core/MessageBus/IMessageBus.cs +44 -16
- package/Runtime/Core/MessageBus/MessageBus.cs +167 -180
- package/Runtime/Core/MessageBus/MessageRegistrationBuilder.cs +44 -0
- package/Runtime/Core/MessageBus/MessagingRegistration.cs +60 -2
- package/Runtime/Core/MessageBus/RegistrationLog.cs +10 -0
- package/Runtime/Core/MessageHandler.cs +107 -6
- package/Runtime/Core/MessageRegistrationHandle.cs +59 -0
- package/Runtime/Core/MessageRegistrationToken.cs +18 -2
- package/Runtime/Core/Messages/ReflexiveMessage.cs +38 -0
- package/Runtime/Core/MessagingDebug.cs +16 -1
- package/Runtime/Unity/CurrentGlobalMessageBusProvider.cs +4 -0
- package/Runtime/Unity/DxMessagingRuntimeInitializer.cs +19 -0
- package/Runtime/Unity/DxMessagingRuntimeInitializer.cs.meta +11 -0
- package/Runtime/Unity/InitialGlobalMessageBusProvider.cs +4 -0
- package/Runtime/Unity/Integrations/Reflex/ReflexRegistrationInstaller.cs +17 -0
- package/Runtime/Unity/Integrations/VContainer/VContainerRegistrationExtensions.cs +8 -0
- package/Runtime/Unity/Integrations/Zenject/ZenjectRegistrationInstaller.cs +12 -0
- package/Runtime/Unity/MessagingComponent.cs +93 -0
- package/Samples~/DI/README.md +13 -13
- package/Samples~/Mini Combat/README.md +15 -15
- package/Samples~/Mini Combat/Walkthrough.md +12 -12
- package/Samples~/UI Buttons + Inspector/README.md +4 -4
- package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/DxAutoConstructorGenerator.cs +4 -0
- package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/DxMessageIdGenerator.cs +4 -0
- package/Tests/Runtime/Core/DiagnosticsTests.cs +3 -3
- package/Tests/Runtime/Core/DxMessagingStaticStateTests.cs +69 -0
- package/Tests/Runtime/Core/DxMessagingStaticStateTests.cs.meta +11 -0
- package/Tests/Runtime/Core/Extensions/MessageBusExtensionsTests.cs +12 -31
- package/Tests/Runtime/Core/OrderingManyRegistrationsTests.cs +683 -0
- package/Tests/Runtime/Core/OrderingManyRegistrationsTests.cs.meta +11 -0
- package/package.json +1 -1
- package/scripts/fix-eol.js +38 -3
- package/Tests/Runtime/WallstopStudios.DxMessaging.Tests.Runtime.csproj +0 -20
- package/Tests/Runtime/WallstopStudios.DxMessaging.Tests.Runtime.csproj.meta +0 -7
|
@@ -2,6 +2,7 @@ namespace DxMessaging.Editor.Settings
|
|
|
2
2
|
{
|
|
3
3
|
#if UNITY_EDITOR
|
|
4
4
|
using System.Collections.Generic;
|
|
5
|
+
using Core.MessageBus;
|
|
5
6
|
using UnityEditor;
|
|
6
7
|
using UnityEngine;
|
|
7
8
|
|
|
@@ -21,6 +22,11 @@ namespace DxMessaging.Editor.Settings
|
|
|
21
22
|
)
|
|
22
23
|
: base(path, scope) { }
|
|
23
24
|
|
|
25
|
+
/// <summary>
|
|
26
|
+
/// Initializes the serialized settings backing store when the settings page is opened.
|
|
27
|
+
/// </summary>
|
|
28
|
+
/// <param name="searchContext">Search text provided by the Project Settings window.</param>
|
|
29
|
+
/// <param name="rootElement">Root visual element for UI Toolkit-based providers.</param>
|
|
24
30
|
public override void OnActivate(
|
|
25
31
|
string searchContext,
|
|
26
32
|
UnityEngine.UIElements.VisualElement rootElement
|
|
@@ -29,28 +35,60 @@ namespace DxMessaging.Editor.Settings
|
|
|
29
35
|
_messagingSettings = DxMessagingSettings.GetSerializedSettings();
|
|
30
36
|
}
|
|
31
37
|
|
|
38
|
+
/// <summary>
|
|
39
|
+
/// Renders the DxMessaging settings UI and persists any modifications.
|
|
40
|
+
/// </summary>
|
|
41
|
+
/// <param name="searchContext">Search text provided by the Project Settings window.</param>
|
|
32
42
|
public override void OnGUI(string searchContext)
|
|
33
43
|
{
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
nameof(DxMessagingSettings._enableDiagnosticsInEditor)
|
|
37
|
-
),
|
|
38
|
-
new GUIContent("Global Diagnostics Mode")
|
|
44
|
+
SerializedProperty targetsProp = _messagingSettings.FindProperty(
|
|
45
|
+
nameof(DxMessagingSettings._diagnosticsTargets)
|
|
39
46
|
);
|
|
47
|
+
DiagnosticsTarget currentTargets = (DiagnosticsTarget)targetsProp.enumValueFlag;
|
|
48
|
+
DiagnosticsTarget updatedTargets = (DiagnosticsTarget)
|
|
49
|
+
EditorGUILayout.EnumFlagsField(
|
|
50
|
+
new GUIContent(
|
|
51
|
+
"Diagnostics Targets",
|
|
52
|
+
"Select where global diagnostics should be enabled by default. Combine flags for multiple targets."
|
|
53
|
+
),
|
|
54
|
+
currentTargets
|
|
55
|
+
);
|
|
56
|
+
if (updatedTargets != currentTargets)
|
|
57
|
+
{
|
|
58
|
+
targetsProp.enumValueFlag = (int)updatedTargets;
|
|
59
|
+
}
|
|
40
60
|
EditorGUILayout.PropertyField(
|
|
41
61
|
_messagingSettings.FindProperty(nameof(DxMessagingSettings._messageBufferSize)),
|
|
42
|
-
new GUIContent(
|
|
62
|
+
new GUIContent(
|
|
63
|
+
"Message Buffer Size",
|
|
64
|
+
"Number of emissions kept per bus/token when diagnostics mode is active."
|
|
65
|
+
)
|
|
66
|
+
);
|
|
67
|
+
EditorGUILayout.PropertyField(
|
|
68
|
+
_messagingSettings.FindProperty(
|
|
69
|
+
nameof(DxMessagingSettings._suppressDomainReloadWarning)
|
|
70
|
+
),
|
|
71
|
+
new GUIContent(
|
|
72
|
+
"Suppress Domain Reload Warning",
|
|
73
|
+
"Disable the warning shown when Enter Play Mode Options skips domain reload; DxMessaging still resets its statics."
|
|
74
|
+
)
|
|
43
75
|
);
|
|
44
76
|
|
|
45
77
|
_messagingSettings.ApplyModifiedProperties();
|
|
46
78
|
}
|
|
47
79
|
|
|
48
80
|
[SettingsProvider]
|
|
81
|
+
/// <summary>
|
|
82
|
+
/// Factory used by Unity to register the DxMessaging project settings page.
|
|
83
|
+
/// </summary>
|
|
84
|
+
/// <returns>Configured settings provider instance.</returns>
|
|
49
85
|
public static SettingsProvider CreateDxMessagingSettingsProvider()
|
|
50
86
|
{
|
|
51
87
|
DxMessagingSettingsProvider provider = new("Project/DxMessaging")
|
|
52
88
|
{
|
|
53
|
-
keywords = new HashSet<string>(
|
|
89
|
+
keywords = new HashSet<string>(
|
|
90
|
+
new[] { "DxMessaging", "Diagnostics", "MessageBus", "Targets" }
|
|
91
|
+
),
|
|
54
92
|
};
|
|
55
93
|
|
|
56
94
|
return provider;
|
package/README.md
CHANGED
|
@@ -52,7 +52,7 @@ Need install instructions for Git URLs, scoped registries, or tarballs? Jump to
|
|
|
52
52
|
|
|
53
53
|
1. **Untargeted** - "Everyone listen!" (pause game, settings changed)
|
|
54
54
|
1. **Targeted** - "Tell Player to heal" (commands to specific entities)
|
|
55
|
-
1. **Broadcast** - "
|
|
55
|
+
1. **Broadcast** - "I took damage" (things that happen to _you_ that others can observe)
|
|
56
56
|
|
|
57
57
|
**One line:** It's the event system Unity should have shipped with - type-safe, leak-proof, and actually debuggable. 🚀
|
|
58
58
|
|
|
@@ -31,30 +31,82 @@ namespace DxMessaging.Core.Attributes
|
|
|
31
31
|
/// Optional default value overloads. Values must be compile-time constants and
|
|
32
32
|
/// will be validated by the source generator against the field type.
|
|
33
33
|
/// </summary>
|
|
34
|
+
/// <summary>
|
|
35
|
+
/// Initializes the attribute with the specified default boolean value.
|
|
36
|
+
/// </summary>
|
|
37
|
+
/// <param name="value">Default value used when the constructor parameter is omitted.</param>
|
|
34
38
|
public DxOptionalParameterAttribute(bool value) { }
|
|
35
39
|
|
|
40
|
+
/// <summary>
|
|
41
|
+
/// Initializes the attribute with the specified default character value.
|
|
42
|
+
/// </summary>
|
|
43
|
+
/// <param name="value">Default value used when the constructor parameter is omitted.</param>
|
|
36
44
|
public DxOptionalParameterAttribute(char value) { }
|
|
37
45
|
|
|
46
|
+
/// <summary>
|
|
47
|
+
/// Initializes the attribute with the specified default string value.
|
|
48
|
+
/// </summary>
|
|
49
|
+
/// <param name="value">Default value used when the constructor parameter is omitted.</param>
|
|
38
50
|
public DxOptionalParameterAttribute(string value) { }
|
|
39
51
|
|
|
52
|
+
/// <summary>
|
|
53
|
+
/// Initializes the attribute with the specified default byte value.
|
|
54
|
+
/// </summary>
|
|
55
|
+
/// <param name="value">Default value used when the constructor parameter is omitted.</param>
|
|
40
56
|
public DxOptionalParameterAttribute(byte value) { }
|
|
41
57
|
|
|
58
|
+
/// <summary>
|
|
59
|
+
/// Initializes the attribute with the specified default signed byte value.
|
|
60
|
+
/// </summary>
|
|
61
|
+
/// <param name="value">Default value used when the constructor parameter is omitted.</param>
|
|
42
62
|
public DxOptionalParameterAttribute(sbyte value) { }
|
|
43
63
|
|
|
64
|
+
/// <summary>
|
|
65
|
+
/// Initializes the attribute with the specified default short value.
|
|
66
|
+
/// </summary>
|
|
67
|
+
/// <param name="value">Default value used when the constructor parameter is omitted.</param>
|
|
44
68
|
public DxOptionalParameterAttribute(short value) { }
|
|
45
69
|
|
|
70
|
+
/// <summary>
|
|
71
|
+
/// Initializes the attribute with the specified default unsigned short value.
|
|
72
|
+
/// </summary>
|
|
73
|
+
/// <param name="value">Default value used when the constructor parameter is omitted.</param>
|
|
46
74
|
public DxOptionalParameterAttribute(ushort value) { }
|
|
47
75
|
|
|
76
|
+
/// <summary>
|
|
77
|
+
/// Initializes the attribute with the specified default integer value.
|
|
78
|
+
/// </summary>
|
|
79
|
+
/// <param name="value">Default value used when the constructor parameter is omitted.</param>
|
|
48
80
|
public DxOptionalParameterAttribute(int value) { }
|
|
49
81
|
|
|
82
|
+
/// <summary>
|
|
83
|
+
/// Initializes the attribute with the specified default unsigned integer value.
|
|
84
|
+
/// </summary>
|
|
85
|
+
/// <param name="value">Default value used when the constructor parameter is omitted.</param>
|
|
50
86
|
public DxOptionalParameterAttribute(uint value) { }
|
|
51
87
|
|
|
88
|
+
/// <summary>
|
|
89
|
+
/// Initializes the attribute with the specified default long value.
|
|
90
|
+
/// </summary>
|
|
91
|
+
/// <param name="value">Default value used when the constructor parameter is omitted.</param>
|
|
52
92
|
public DxOptionalParameterAttribute(long value) { }
|
|
53
93
|
|
|
94
|
+
/// <summary>
|
|
95
|
+
/// Initializes the attribute with the specified default unsigned long value.
|
|
96
|
+
/// </summary>
|
|
97
|
+
/// <param name="value">Default value used when the constructor parameter is omitted.</param>
|
|
54
98
|
public DxOptionalParameterAttribute(ulong value) { }
|
|
55
99
|
|
|
100
|
+
/// <summary>
|
|
101
|
+
/// Initializes the attribute with the specified default single-precision floating point value.
|
|
102
|
+
/// </summary>
|
|
103
|
+
/// <param name="value">Default value used when the constructor parameter is omitted.</param>
|
|
56
104
|
public DxOptionalParameterAttribute(float value) { }
|
|
57
105
|
|
|
106
|
+
/// <summary>
|
|
107
|
+
/// Initializes the attribute with the specified default double-precision floating point value.
|
|
108
|
+
/// </summary>
|
|
109
|
+
/// <param name="value">Default value used when the constructor parameter is omitted.</param>
|
|
58
110
|
public DxOptionalParameterAttribute(double value) { }
|
|
59
111
|
|
|
60
112
|
/// <summary>
|
|
@@ -29,6 +29,10 @@ namespace DxMessaging.Core.DataStructure
|
|
|
29
29
|
_current = default;
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
+
/// <summary>
|
|
33
|
+
/// Advances the enumerator to the next element in chronological order.
|
|
34
|
+
/// </summary>
|
|
35
|
+
/// <returns><c>true</c> when another element is available; otherwise <c>false</c>.</returns>
|
|
32
36
|
public bool MoveNext()
|
|
33
37
|
{
|
|
34
38
|
if (++_index < _buffer.Count)
|
|
@@ -41,16 +45,25 @@ namespace DxMessaging.Core.DataStructure
|
|
|
41
45
|
return false;
|
|
42
46
|
}
|
|
43
47
|
|
|
48
|
+
/// <summary>
|
|
49
|
+
/// Gets the element at the current enumerator position.
|
|
50
|
+
/// </summary>
|
|
44
51
|
public T Current => _current;
|
|
45
52
|
|
|
46
53
|
object IEnumerator.Current => Current;
|
|
47
54
|
|
|
55
|
+
/// <summary>
|
|
56
|
+
/// Resets the enumerator to its initial position before the first element.
|
|
57
|
+
/// </summary>
|
|
48
58
|
public void Reset()
|
|
49
59
|
{
|
|
50
60
|
_index = -1;
|
|
51
61
|
_current = default;
|
|
52
62
|
}
|
|
53
63
|
|
|
64
|
+
/// <summary>
|
|
65
|
+
/// Releases resources held by the enumerator.
|
|
66
|
+
/// </summary>
|
|
54
67
|
public void Dispose() { }
|
|
55
68
|
}
|
|
56
69
|
|
|
@@ -107,6 +120,9 @@ namespace DxMessaging.Core.DataStructure
|
|
|
107
120
|
}
|
|
108
121
|
}
|
|
109
122
|
|
|
123
|
+
/// <summary>
|
|
124
|
+
/// Creates an enumerator that iterates from the oldest element to the most recently added.
|
|
125
|
+
/// </summary>
|
|
110
126
|
public CyclicBufferEnumerator GetEnumerator()
|
|
111
127
|
{
|
|
112
128
|
return new CyclicBufferEnumerator(this);
|
|
@@ -12,7 +12,7 @@ namespace DxMessaging.Core.Diagnostics
|
|
|
12
12
|
/// Captures a snapshot of a message emission for diagnostics.
|
|
13
13
|
/// </summary>
|
|
14
14
|
/// <remarks>
|
|
15
|
-
/// When diagnostics are enabled (see <see cref="MessageBus.IMessageBus.
|
|
15
|
+
/// When diagnostics are enabled (see <see cref="MessageBus.IMessageBus.GlobalDiagnosticsTargets"/>),
|
|
16
16
|
/// the bus and tokens record recent emissions in ring buffers along with a trimmed stack trace
|
|
17
17
|
/// that excludes DxMessaging internals for easier debugging.
|
|
18
18
|
///
|
|
@@ -1,21 +1,83 @@
|
|
|
1
1
|
namespace DxMessaging.Core.Diagnostics
|
|
2
2
|
{
|
|
3
|
+
/// <summary>
|
|
4
|
+
/// Categories used when recording registrations in diagnostics logs.
|
|
5
|
+
/// </summary>
|
|
3
6
|
public enum MessageRegistrationType
|
|
4
7
|
{
|
|
8
|
+
/// <summary>
|
|
9
|
+
/// No registration type was captured.
|
|
10
|
+
/// </summary>
|
|
5
11
|
None = 0,
|
|
12
|
+
|
|
13
|
+
/// <summary>
|
|
14
|
+
/// A targeted handler that listens for messages addressed to a specific <see cref="Core.InstanceId"/>.
|
|
15
|
+
/// </summary>
|
|
6
16
|
Targeted = 1,
|
|
17
|
+
|
|
18
|
+
/// <summary>
|
|
19
|
+
/// A global untargeted handler that receives all messages of a given type.
|
|
20
|
+
/// </summary>
|
|
7
21
|
Untargeted = 2,
|
|
22
|
+
|
|
23
|
+
/// <summary>
|
|
24
|
+
/// A broadcast handler that listens for messages emitted from a source <see cref="Core.InstanceId"/>.
|
|
25
|
+
/// </summary>
|
|
8
26
|
Broadcast = 3,
|
|
27
|
+
|
|
28
|
+
/// <summary>
|
|
29
|
+
/// A broadcast post-processor that runs after broadcast handlers complete.
|
|
30
|
+
/// </summary>
|
|
9
31
|
BroadcastPostProcessor = 4,
|
|
32
|
+
|
|
33
|
+
/// <summary>
|
|
34
|
+
/// A targeted post-processor that runs after targeted handlers complete.
|
|
35
|
+
/// </summary>
|
|
10
36
|
TargetedPostProcessor = 5,
|
|
37
|
+
|
|
38
|
+
/// <summary>
|
|
39
|
+
/// A targeted handler that ignores the concrete target during invocation.
|
|
40
|
+
/// </summary>
|
|
11
41
|
TargetedWithoutTargeting = 6,
|
|
42
|
+
|
|
43
|
+
/// <summary>
|
|
44
|
+
/// A post-processor for handlers registered without a concrete target.
|
|
45
|
+
/// </summary>
|
|
12
46
|
TargetedWithoutTargetingPostProcessor = 7,
|
|
47
|
+
|
|
48
|
+
/// <summary>
|
|
49
|
+
/// A broadcast handler registered without an explicit source identity.
|
|
50
|
+
/// </summary>
|
|
13
51
|
BroadcastWithoutSource = 8,
|
|
52
|
+
|
|
53
|
+
/// <summary>
|
|
54
|
+
/// A post-processor for broadcast handlers registered without an explicit source.
|
|
55
|
+
/// </summary>
|
|
14
56
|
BroadcastWithoutSourcePostProcessor = 9,
|
|
57
|
+
|
|
58
|
+
/// <summary>
|
|
59
|
+
/// A post-processor that runs after untargeted handlers complete.
|
|
60
|
+
/// </summary>
|
|
15
61
|
UntargetedPostProcessor = 10,
|
|
62
|
+
|
|
63
|
+
/// <summary>
|
|
64
|
+
/// A global catch-all registration that observes every message.
|
|
65
|
+
/// </summary>
|
|
16
66
|
GlobalAcceptAll = 11,
|
|
67
|
+
|
|
68
|
+
/// <summary>
|
|
69
|
+
/// An untargeted interceptor that can mutate or cancel global messages.
|
|
70
|
+
/// </summary>
|
|
17
71
|
UntargetedInterceptor = 12,
|
|
72
|
+
|
|
73
|
+
/// <summary>
|
|
74
|
+
/// A targeted interceptor that can mutate or cancel messages bound to a specific recipient.
|
|
75
|
+
/// </summary>
|
|
18
76
|
TargetedInterceptor = 13,
|
|
77
|
+
|
|
78
|
+
/// <summary>
|
|
79
|
+
/// A broadcast interceptor that can mutate or cancel messages emitted from a source.
|
|
80
|
+
/// </summary>
|
|
19
81
|
BroadcastInterceptor = 14,
|
|
20
82
|
}
|
|
21
83
|
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
namespace DxMessaging.Core
|
|
2
|
+
{
|
|
3
|
+
using System;
|
|
4
|
+
using Helper;
|
|
5
|
+
using MessageBus;
|
|
6
|
+
|
|
7
|
+
/// <summary>
|
|
8
|
+
/// Centralised utility for resetting DxMessaging static state when Domain Reload is disabled.
|
|
9
|
+
/// </summary>
|
|
10
|
+
public static class DxMessagingStaticState
|
|
11
|
+
{
|
|
12
|
+
private static readonly object ResetLock = new object();
|
|
13
|
+
private static readonly BaselineState Baseline;
|
|
14
|
+
|
|
15
|
+
static DxMessagingStaticState()
|
|
16
|
+
{
|
|
17
|
+
Baseline = CaptureBaseline();
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/// <summary>
|
|
21
|
+
/// Resets all static variables in DxMessaging to their default values.
|
|
22
|
+
/// </summary>
|
|
23
|
+
public static void Reset()
|
|
24
|
+
{
|
|
25
|
+
lock (ResetLock)
|
|
26
|
+
{
|
|
27
|
+
MessagingDebug.enabled = Baseline.MessagingDebugEnabled;
|
|
28
|
+
MessagingDebug.LogFunction = Baseline.MessagingDebugLogFunction;
|
|
29
|
+
|
|
30
|
+
IMessageBus.GlobalDiagnosticsTargets = Baseline.GlobalDiagnosticsTargets;
|
|
31
|
+
IMessageBus.GlobalMessageBufferSize = Baseline.GlobalMessageBufferSize;
|
|
32
|
+
IMessageBus.GlobalSequentialIndex = Baseline.GlobalSequentialIndex;
|
|
33
|
+
|
|
34
|
+
MessageHelperIndexer.RestoreState(Baseline.HelperState);
|
|
35
|
+
|
|
36
|
+
MessageRegistrationHandle.SetIdSeed(Baseline.MessageRegistrationHandleSeed);
|
|
37
|
+
MessageRegistrationBuilder.SetSyntheticOwnerCounter(Baseline.SyntheticOwnerCounter);
|
|
38
|
+
|
|
39
|
+
MessageHandler.ResetStatics();
|
|
40
|
+
IMessageBus.GlobalSequentialIndex = Baseline.GlobalSequentialIndex;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
private static BaselineState CaptureBaseline()
|
|
45
|
+
{
|
|
46
|
+
bool messagingDebugEnabled = MessagingDebug.enabled;
|
|
47
|
+
Action<LogLevel, string> messagingDebugLogFunction = MessagingDebug.LogFunction;
|
|
48
|
+
DiagnosticsTarget globalDiagnosticsTargets = IMessageBus.GlobalDiagnosticsTargets;
|
|
49
|
+
int globalMessageBufferSize = IMessageBus.GlobalMessageBufferSize;
|
|
50
|
+
int globalSequentialIndex = IMessageBus.GlobalSequentialIndex;
|
|
51
|
+
long messageRegistrationHandleSeed = MessageRegistrationHandle.GetCurrentIdSeed();
|
|
52
|
+
int syntheticOwnerCounter = MessageRegistrationBuilder.GetSyntheticOwnerCounter();
|
|
53
|
+
MessageHelperIndexer.MessageHelperIndexerState helperState =
|
|
54
|
+
MessageHelperIndexer.CaptureState();
|
|
55
|
+
|
|
56
|
+
return new BaselineState(
|
|
57
|
+
messagingDebugEnabled,
|
|
58
|
+
messagingDebugLogFunction,
|
|
59
|
+
globalDiagnosticsTargets,
|
|
60
|
+
globalMessageBufferSize,
|
|
61
|
+
globalSequentialIndex,
|
|
62
|
+
messageRegistrationHandleSeed,
|
|
63
|
+
syntheticOwnerCounter,
|
|
64
|
+
helperState
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
private sealed class BaselineState
|
|
69
|
+
{
|
|
70
|
+
internal BaselineState(
|
|
71
|
+
bool messagingDebugEnabled,
|
|
72
|
+
Action<LogLevel, string> messagingDebugLogFunction,
|
|
73
|
+
DiagnosticsTarget globalDiagnosticsTargets,
|
|
74
|
+
int globalMessageBufferSize,
|
|
75
|
+
int globalSequentialIndex,
|
|
76
|
+
long messageRegistrationHandleSeed,
|
|
77
|
+
int syntheticOwnerCounter,
|
|
78
|
+
MessageHelperIndexer.MessageHelperIndexerState helperState
|
|
79
|
+
)
|
|
80
|
+
{
|
|
81
|
+
MessagingDebugEnabled = messagingDebugEnabled;
|
|
82
|
+
MessagingDebugLogFunction = messagingDebugLogFunction;
|
|
83
|
+
GlobalDiagnosticsTargets = globalDiagnosticsTargets;
|
|
84
|
+
GlobalMessageBufferSize = globalMessageBufferSize;
|
|
85
|
+
GlobalSequentialIndex = globalSequentialIndex;
|
|
86
|
+
MessageRegistrationHandleSeed = messageRegistrationHandleSeed;
|
|
87
|
+
SyntheticOwnerCounter = syntheticOwnerCounter;
|
|
88
|
+
HelperState = helperState;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
internal bool MessagingDebugEnabled { get; }
|
|
92
|
+
|
|
93
|
+
internal Action<LogLevel, string> MessagingDebugLogFunction { get; }
|
|
94
|
+
|
|
95
|
+
internal DiagnosticsTarget GlobalDiagnosticsTargets { get; }
|
|
96
|
+
|
|
97
|
+
internal int GlobalMessageBufferSize { get; }
|
|
98
|
+
|
|
99
|
+
internal int GlobalSequentialIndex { get; }
|
|
100
|
+
|
|
101
|
+
internal long MessageRegistrationHandleSeed { get; }
|
|
102
|
+
|
|
103
|
+
internal int SyntheticOwnerCounter { get; }
|
|
104
|
+
|
|
105
|
+
internal MessageHelperIndexer.MessageHelperIndexerState HelperState { get; }
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
@@ -5,6 +5,22 @@ namespace DxMessaging.Core.Extensions
|
|
|
5
5
|
|
|
6
6
|
internal static class IListExtensions
|
|
7
7
|
{
|
|
8
|
+
/// <summary>
|
|
9
|
+
/// Rotates the list contents in-place by the specified offset.
|
|
10
|
+
/// </summary>
|
|
11
|
+
/// <typeparam name="T">Element type held by the list.</typeparam>
|
|
12
|
+
/// <param name="list">List to rotate. Must have at least two elements to perform work.</param>
|
|
13
|
+
/// <param name="amount">
|
|
14
|
+
/// Number of positions to rotate. Positive values move elements toward the end (wrapping),
|
|
15
|
+
/// negative values move them toward the start.
|
|
16
|
+
/// </param>
|
|
17
|
+
/// <example>
|
|
18
|
+
/// <code>
|
|
19
|
+
/// var numbers = new List<int> { 1, 2, 3, 4 };
|
|
20
|
+
/// numbers.Shift(1); // numbers becomes { 4, 1, 2, 3 }
|
|
21
|
+
/// numbers.Shift(-2); // numbers becomes { 2, 3, 4, 1 }
|
|
22
|
+
/// </code>
|
|
23
|
+
/// </example>
|
|
8
24
|
public static void Shift<T>(this IList<T> list, int amount)
|
|
9
25
|
{
|
|
10
26
|
if (list is not { Count: > 1 })
|
|
@@ -26,6 +42,14 @@ namespace DxMessaging.Core.Extensions
|
|
|
26
42
|
Reverse(list, amount, count - 1);
|
|
27
43
|
}
|
|
28
44
|
|
|
45
|
+
/// <summary>
|
|
46
|
+
/// Reverses the order of elements in-place within the inclusive range.
|
|
47
|
+
/// </summary>
|
|
48
|
+
/// <typeparam name="T">Element type held by the list.</typeparam>
|
|
49
|
+
/// <param name="list">List whose segment should be reversed.</param>
|
|
50
|
+
/// <param name="start">Zero-based index of the first element in the range.</param>
|
|
51
|
+
/// <param name="end">Zero-based index of the last element in the range.</param>
|
|
52
|
+
/// <exception cref="ArgumentException">Thrown when the start or end value is outside the list bounds.</exception>
|
|
29
53
|
public static void Reverse<T>(this IList<T> list, int start, int end)
|
|
30
54
|
{
|
|
31
55
|
if (start < 0 || list.Count <= start)
|