com.wallstop-studios.dxmessaging 2.0.0-rc07 → 2.0.0-rc08

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.
@@ -81,8 +81,8 @@
81
81
  private readonly Stack<
82
82
  List<KeyValuePair<int, Dictionary<MessageHandler, int>>>
83
83
  > _sortedHandlers = new();
84
- private readonly Stack<List<object>> _interceptors = new();
85
- private readonly Stack<List<int>> _interceptorKeys = new();
84
+ private readonly Stack<List<List<object>>> _interceptors = new();
85
+ private readonly Stack<List<object>> _innerInterceptorsStack = new();
86
86
 
87
87
  public Action RegisterUntargeted<T>(MessageHandler messageHandler, int priority = 0)
88
88
  where T : IUntargetedMessage
@@ -969,26 +969,36 @@
969
969
 
970
970
  private bool TryGetInterceptorCaches(
971
971
  Type type,
972
- out SortedDictionary<int, List<object>> interceptors,
973
- out List<int> interceptorKeys,
974
- out List<object> interceptorStack
972
+ out List<List<object>> interceptorStack,
973
+ out List<object> interceptorObjects
975
974
  )
976
975
  {
977
- if (!_interceptsByType.TryGetValue(type, out interceptors) || interceptors.Count <= 0)
976
+ if (
977
+ !_interceptsByType.TryGetValue(
978
+ type,
979
+ out SortedDictionary<int, List<object>> interceptors
980
+ )
981
+ || interceptors.Count <= 0
982
+ )
978
983
  {
979
- interceptorKeys = default;
980
984
  interceptorStack = default;
985
+ interceptorObjects = default;
981
986
  return false;
982
987
  }
983
988
 
984
989
  if (!_interceptors.TryPop(out interceptorStack))
985
990
  {
986
- interceptorStack = new List<object>();
991
+ interceptorStack = new List<List<object>>(interceptors.Values);
992
+ }
993
+ else
994
+ {
995
+ interceptorStack.Clear();
996
+ interceptorStack.AddRange(interceptors.Values);
987
997
  }
988
998
 
989
- if (!_interceptorKeys.TryPop(out interceptorKeys))
999
+ if (!_innerInterceptorsStack.TryPop(out interceptorObjects))
990
1000
  {
991
- interceptorKeys = new List<int>();
1001
+ interceptorObjects = new List<object>();
992
1002
  }
993
1003
 
994
1004
  return true;
@@ -1000,9 +1010,8 @@
1000
1010
  if (
1001
1011
  !TryGetInterceptorCaches(
1002
1012
  type,
1003
- out SortedDictionary<int, List<object>> interceptors,
1004
- out List<int> interceptorKeys,
1005
- out List<object> interceptorStack
1013
+ out List<List<object>> interceptorStack,
1014
+ out List<object> interceptorObjects
1006
1015
  )
1007
1016
  )
1008
1017
  {
@@ -1011,22 +1020,12 @@
1011
1020
 
1012
1021
  try
1013
1022
  {
1014
- interceptorKeys.Clear();
1015
- interceptorKeys.AddRange(interceptors.Keys);
1016
- foreach (int priority in interceptorKeys)
1023
+ foreach (List<object> stack in interceptorStack)
1017
1024
  {
1018
- if (
1019
- !interceptors.TryGetValue(priority, out List<object> untypedInterceptors)
1020
- || untypedInterceptors.Count <= 0
1021
- )
1022
- {
1023
- continue;
1024
- }
1025
+ interceptorObjects.Clear();
1026
+ interceptorObjects.AddRange(stack);
1025
1027
 
1026
- interceptorStack.Clear();
1027
- interceptorStack.AddRange(untypedInterceptors);
1028
-
1029
- foreach (object transformer in interceptorStack)
1028
+ foreach (object transformer in interceptorObjects)
1030
1029
  {
1031
1030
  if (transformer is not UntargetedInterceptor<T> typedTransformer)
1032
1031
  {
@@ -1043,7 +1042,7 @@
1043
1042
  finally
1044
1043
  {
1045
1044
  _interceptors.Push(interceptorStack);
1046
- _interceptorKeys.Push(interceptorKeys);
1045
+ _innerInterceptorsStack.Push(interceptorObjects);
1047
1046
  }
1048
1047
 
1049
1048
  return true;
@@ -1055,9 +1054,8 @@
1055
1054
  if (
1056
1055
  !TryGetInterceptorCaches(
1057
1056
  type,
1058
- out SortedDictionary<int, List<object>> interceptors,
1059
- out List<int> interceptorKeys,
1060
- out List<object> interceptorStack
1057
+ out List<List<object>> interceptorStack,
1058
+ out List<object> interceptorObjects
1061
1059
  )
1062
1060
  )
1063
1061
  {
@@ -1066,22 +1064,12 @@
1066
1064
 
1067
1065
  try
1068
1066
  {
1069
- interceptorKeys.Clear();
1070
- interceptorKeys.AddRange(interceptors.Keys);
1071
- foreach (int priority in interceptorKeys)
1067
+ foreach (List<object> stack in interceptorStack)
1072
1068
  {
1073
- if (
1074
- !interceptors.TryGetValue(priority, out List<object> untypedInterceptors)
1075
- || untypedInterceptors.Count <= 0
1076
- )
1077
- {
1078
- continue;
1079
- }
1080
-
1081
- interceptorStack.Clear();
1082
- interceptorStack.AddRange(untypedInterceptors);
1069
+ interceptorObjects.Clear();
1070
+ interceptorObjects.AddRange(stack);
1083
1071
 
1084
- foreach (object transformer in interceptorStack)
1072
+ foreach (object transformer in interceptorObjects)
1085
1073
  {
1086
1074
  if (transformer is not TargetedInterceptor<T> typedTransformer)
1087
1075
  {
@@ -1098,7 +1086,7 @@
1098
1086
  finally
1099
1087
  {
1100
1088
  _interceptors.Push(interceptorStack);
1101
- _interceptorKeys.Push(interceptorKeys);
1089
+ _innerInterceptorsStack.Push(interceptorObjects);
1102
1090
  }
1103
1091
 
1104
1092
  return true;
@@ -1110,9 +1098,8 @@
1110
1098
  if (
1111
1099
  !TryGetInterceptorCaches(
1112
1100
  type,
1113
- out SortedDictionary<int, List<object>> interceptors,
1114
- out List<int> interceptorKeys,
1115
- out List<object> interceptorStack
1101
+ out List<List<object>> interceptorStack,
1102
+ out List<object> interceptorObjects
1116
1103
  )
1117
1104
  )
1118
1105
  {
@@ -1121,22 +1108,12 @@
1121
1108
 
1122
1109
  try
1123
1110
  {
1124
- interceptorKeys.Clear();
1125
- interceptorKeys.AddRange(interceptors.Keys);
1126
- foreach (int priority in interceptorKeys)
1111
+ foreach (List<object> stack in interceptorStack)
1127
1112
  {
1128
- if (
1129
- !interceptors.TryGetValue(priority, out List<object> untypedInterceptors)
1130
- || untypedInterceptors.Count <= 0
1131
- )
1132
- {
1133
- continue;
1134
- }
1135
-
1136
- interceptorStack.Clear();
1137
- interceptorStack.AddRange(untypedInterceptors);
1113
+ interceptorObjects.Clear();
1114
+ interceptorObjects.AddRange(stack);
1138
1115
 
1139
- foreach (object transformer in interceptorStack)
1116
+ foreach (object transformer in interceptorObjects)
1140
1117
  {
1141
1118
  if (transformer is not BroadcastInterceptor<T> typedTransformer)
1142
1119
  {
@@ -1153,7 +1130,7 @@
1153
1130
  finally
1154
1131
  {
1155
1132
  _interceptors.Push(interceptorStack);
1156
- _interceptorKeys.Push(interceptorKeys);
1133
+ _innerInterceptorsStack.Push(interceptorObjects);
1157
1134
  }
1158
1135
 
1159
1136
  return true;
@@ -1333,45 +1333,42 @@
1333
1333
 
1334
1334
  private Dictionary<
1335
1335
  InstanceId,
1336
- SortedDictionary<int, Dictionary<Action<T>, int>>
1336
+ Dictionary<int, Dictionary<Action<T>, int>>
1337
1337
  > _targetedHandlers;
1338
- private SortedDictionary<int, Dictionary<Action<T>, int>> _untargetedHandlers;
1338
+ private Dictionary<int, Dictionary<Action<T>, int>> _untargetedHandlers;
1339
1339
  private Dictionary<
1340
1340
  InstanceId,
1341
- SortedDictionary<int, Dictionary<Action<T>, int>>
1341
+ Dictionary<int, Dictionary<Action<T>, int>>
1342
1342
  > _broadcastHandlers;
1343
1343
  private Dictionary<
1344
1344
  InstanceId,
1345
- SortedDictionary<int, Dictionary<Action<T>, int>>
1345
+ Dictionary<int, Dictionary<Action<T>, int>>
1346
1346
  > _targetedPostProcessingHandlers;
1347
- private SortedDictionary<
1348
- int,
1349
- Dictionary<Action<T>, int>
1350
- > _untargetedPostProcessingHandlers;
1347
+ private Dictionary<int, Dictionary<Action<T>, int>> _untargetedPostProcessingHandlers;
1351
1348
  private Dictionary<
1352
1349
  InstanceId,
1353
- SortedDictionary<int, Dictionary<Action<T>, int>>
1350
+ Dictionary<int, Dictionary<Action<T>, int>>
1354
1351
  > _broadcastPostProcessingHandlers;
1355
1352
  private Dictionary<
1356
1353
  InstanceId,
1357
- SortedDictionary<int, Dictionary<FastHandler<T>, int>>
1354
+ Dictionary<int, Dictionary<FastHandler<T>, int>>
1358
1355
  > _targetedFastHandlers;
1359
- private SortedDictionary<int, Dictionary<FastHandler<T>, int>> _untargetedFastHandlers;
1356
+ private Dictionary<int, Dictionary<FastHandler<T>, int>> _untargetedFastHandlers;
1360
1357
  private Dictionary<
1361
1358
  InstanceId,
1362
- SortedDictionary<int, Dictionary<FastHandler<T>, int>>
1359
+ Dictionary<int, Dictionary<FastHandler<T>, int>>
1363
1360
  > _broadcastFastHandlers;
1364
1361
  private Dictionary<
1365
1362
  InstanceId,
1366
- SortedDictionary<int, Dictionary<FastHandler<T>, int>>
1363
+ Dictionary<int, Dictionary<FastHandler<T>, int>>
1367
1364
  > _targetedPostProcessingFastHandlers;
1368
- private SortedDictionary<
1365
+ private Dictionary<
1369
1366
  int,
1370
1367
  Dictionary<FastHandler<T>, int>
1371
1368
  > _untargetedPostProcessingFastHandlers;
1372
1369
  private Dictionary<
1373
1370
  InstanceId,
1374
- SortedDictionary<int, Dictionary<FastHandler<T>, int>>
1371
+ Dictionary<int, Dictionary<FastHandler<T>, int>>
1375
1372
  > _broadcastPostProcessingFastHandlers;
1376
1373
  private Dictionary<Action<IUntargetedMessage>, int> _globalUntargetedHandlers;
1377
1374
  private Dictionary<Action<InstanceId, ITargetedMessage>, int> _globalTargetedHandlers;
@@ -1385,35 +1382,35 @@
1385
1382
  FastHandlerWithContext<IBroadcastMessage>,
1386
1383
  int
1387
1384
  > _globalBroadcastFastHandlers;
1388
- private SortedDictionary<
1385
+ private Dictionary<
1389
1386
  int,
1390
1387
  Dictionary<Action<InstanceId, T>, int>
1391
1388
  > _targetedWithoutTargetingHandlers;
1392
- private SortedDictionary<
1389
+ private Dictionary<
1393
1390
  int,
1394
1391
  Dictionary<FastHandlerWithContext<T>, int>
1395
1392
  > _fastTargetedWithoutTargetingHandlers;
1396
- private SortedDictionary<
1393
+ private Dictionary<
1397
1394
  int,
1398
1395
  Dictionary<Action<InstanceId, T>, int>
1399
1396
  > _broadcastWithoutSourceHandlers;
1400
- private SortedDictionary<
1397
+ private Dictionary<
1401
1398
  int,
1402
1399
  Dictionary<FastHandlerWithContext<T>, int>
1403
1400
  > _fastBroadcastWithoutSourceHandlers;
1404
- private SortedDictionary<
1401
+ private Dictionary<
1405
1402
  int,
1406
1403
  Dictionary<Action<InstanceId, T>, int>
1407
1404
  > _targetedWithoutTargetingPostProcessingHandlers;
1408
- private SortedDictionary<
1405
+ private Dictionary<
1409
1406
  int,
1410
1407
  Dictionary<FastHandlerWithContext<T>, int>
1411
1408
  > _fastTargetedWithoutTargetingPostProcessingHandlers;
1412
- private SortedDictionary<
1409
+ private Dictionary<
1413
1410
  int,
1414
1411
  Dictionary<Action<InstanceId, T>, int>
1415
1412
  > _broadcastWithoutSourcePostProcessingHandlers;
1416
- private SortedDictionary<
1413
+ private Dictionary<
1417
1414
  int,
1418
1415
  Dictionary<FastHandlerWithContext<T>, int>
1419
1416
  > _fastBroadcastWithoutSourcePostProcessingHandlers;
@@ -2249,10 +2246,7 @@
2249
2246
 
2250
2247
  private static void RunFastHandlersWithContext<TMessage>(
2251
2248
  ref InstanceId context,
2252
- SortedDictionary<
2253
- int,
2254
- Dictionary<FastHandlerWithContext<T>, int>
2255
- > fastHandlersByContext,
2249
+ Dictionary<int, Dictionary<FastHandlerWithContext<T>, int>> fastHandlersByContext,
2256
2250
  ref TMessage message,
2257
2251
  int priority
2258
2252
  )
@@ -2276,7 +2270,7 @@
2276
2270
  ref InstanceId context,
2277
2271
  Dictionary<
2278
2272
  InstanceId,
2279
- SortedDictionary<int, Dictionary<FastHandler<T>, int>>
2273
+ Dictionary<int, Dictionary<FastHandler<T>, int>>
2280
2274
  > fastHandlersByContext,
2281
2275
  ref TMessage message,
2282
2276
  int priority
@@ -2287,7 +2281,7 @@
2287
2281
  fastHandlersByContext is not { Count: > 0 }
2288
2282
  || !fastHandlersByContext.TryGetValue(
2289
2283
  context,
2290
- out SortedDictionary<int, Dictionary<FastHandler<T>, int>> fastHandlers
2284
+ out Dictionary<int, Dictionary<FastHandler<T>, int>> fastHandlers
2291
2285
  )
2292
2286
  )
2293
2287
  {
@@ -2298,7 +2292,7 @@
2298
2292
  }
2299
2293
 
2300
2294
  private static void RunFastHandlers<TMessage>(
2301
- SortedDictionary<int, Dictionary<FastHandler<T>, int>> fastHandlers,
2295
+ Dictionary<int, Dictionary<FastHandler<T>, int>> fastHandlers,
2302
2296
  ref TMessage message,
2303
2297
  int priority
2304
2298
  )
@@ -2406,7 +2400,7 @@
2406
2400
  private static void RunFastHandlers<TMessage, U>(
2407
2401
  ref InstanceId context,
2408
2402
  ref Stack<List<FastHandlerWithContext<U>>> stack,
2409
- SortedDictionary<int, Dictionary<FastHandlerWithContext<U>, int>> fastHandlers,
2403
+ Dictionary<int, Dictionary<FastHandlerWithContext<U>, int>> fastHandlers,
2410
2404
  ref TMessage message,
2411
2405
  int priority
2412
2406
  )
@@ -2451,7 +2445,7 @@
2451
2445
  ref InstanceId context,
2452
2446
  Dictionary<
2453
2447
  InstanceId,
2454
- SortedDictionary<int, Dictionary<Action<T>, int>>
2448
+ Dictionary<int, Dictionary<Action<T>, int>>
2455
2449
  > handlersByContext,
2456
2450
  ref TMessage message,
2457
2451
  int priority
@@ -2462,7 +2456,7 @@
2462
2456
  handlersByContext is not { Count: > 0 }
2463
2457
  || !handlersByContext.TryGetValue(
2464
2458
  context,
2465
- out SortedDictionary<int, Dictionary<Action<T>, int>> handlers
2459
+ out Dictionary<int, Dictionary<Action<T>, int>> handlers
2466
2460
  )
2467
2461
  )
2468
2462
  {
@@ -2473,7 +2467,7 @@
2473
2467
  }
2474
2468
 
2475
2469
  private static void RunHandlers<TMessage>(
2476
- SortedDictionary<int, Dictionary<Action<T>, int>> sortedHandlers,
2470
+ Dictionary<int, Dictionary<Action<T>, int>> sortedHandlers,
2477
2471
  ref TMessage message,
2478
2472
  int priority
2479
2473
  )
@@ -2510,7 +2504,7 @@
2510
2504
 
2511
2505
  private static void RunHandlers<TMessage>(
2512
2506
  ref InstanceId context,
2513
- SortedDictionary<int, Dictionary<Action<InstanceId, T>, int>> handlers,
2507
+ Dictionary<int, Dictionary<Action<InstanceId, T>, int>> handlers,
2514
2508
  ref TMessage message,
2515
2509
  int priority
2516
2510
  )
@@ -2568,26 +2562,23 @@
2568
2562
 
2569
2563
  private static Action AddHandler<U>(
2570
2564
  InstanceId context,
2571
- ref Dictionary<
2572
- InstanceId,
2573
- SortedDictionary<int, Dictionary<U, int>>
2574
- > handlersByContext,
2565
+ ref Dictionary<InstanceId, Dictionary<int, Dictionary<U, int>>> handlersByContext,
2575
2566
  U handler,
2576
2567
  Action deregistration,
2577
2568
  int priority
2578
2569
  )
2579
2570
  {
2580
2571
  handlersByContext ??=
2581
- new Dictionary<InstanceId, SortedDictionary<int, Dictionary<U, int>>>();
2572
+ new Dictionary<InstanceId, Dictionary<int, Dictionary<U, int>>>();
2582
2573
 
2583
2574
  if (
2584
2575
  !handlersByContext.TryGetValue(
2585
2576
  context,
2586
- out SortedDictionary<int, Dictionary<U, int>> sortedHandlers
2577
+ out Dictionary<int, Dictionary<U, int>> sortedHandlers
2587
2578
  )
2588
2579
  )
2589
2580
  {
2590
- sortedHandlers = new SortedDictionary<int, Dictionary<U, int>>();
2581
+ sortedHandlers = new Dictionary<int, Dictionary<U, int>>();
2591
2582
  handlersByContext[context] = sortedHandlers;
2592
2583
  }
2593
2584
 
@@ -2601,10 +2592,8 @@
2601
2592
 
2602
2593
  handlers[handler] = count + 1;
2603
2594
 
2604
- Dictionary<
2605
- InstanceId,
2606
- SortedDictionary<int, Dictionary<U, int>>
2607
- > localHandlersByContext = handlersByContext;
2595
+ Dictionary<InstanceId, Dictionary<int, Dictionary<U, int>>> localHandlersByContext =
2596
+ handlersByContext;
2608
2597
 
2609
2598
  return () =>
2610
2599
  {
@@ -2675,13 +2664,13 @@
2675
2664
  }
2676
2665
 
2677
2666
  private static Action AddHandler<U>(
2678
- ref SortedDictionary<int, Dictionary<U, int>> sortedHandlers,
2667
+ ref Dictionary<int, Dictionary<U, int>> sortedHandlers,
2679
2668
  U handler,
2680
2669
  Action deregistration,
2681
2670
  int priority
2682
2671
  )
2683
2672
  {
2684
- sortedHandlers ??= new SortedDictionary<int, Dictionary<U, int>>();
2673
+ sortedHandlers ??= new Dictionary<int, Dictionary<U, int>>();
2685
2674
 
2686
2675
  if (
2687
2676
  !sortedHandlers.TryGetValue(priority, out Dictionary<U, int> handlersByPriority)
@@ -2695,7 +2684,7 @@
2695
2684
 
2696
2685
  handlersByPriority[handler] = count + 1;
2697
2686
 
2698
- SortedDictionary<int, Dictionary<U, int>> localSortedHandlers = sortedHandlers;
2687
+ Dictionary<int, Dictionary<U, int>> localSortedHandlers = sortedHandlers;
2699
2688
  Dictionary<U, int> localHandlers = handlersByPriority;
2700
2689
 
2701
2690
  return () =>
@@ -6,6 +6,7 @@
6
6
  using Core;
7
7
  using DxMessaging.Core;
8
8
  using DxMessaging.Core.Extensions;
9
+ using global::Unity.PerformanceTesting;
9
10
  using NUnit.Framework;
10
11
  using Scripts.Components;
11
12
  using Scripts.Messages;
@@ -20,7 +21,7 @@
20
21
  public override void Setup()
21
22
  {
22
23
  base.Setup();
23
- MessagingDebug.LogFunction = (_1, _2) => { };
24
+ MessagingDebug.LogFunction = (_, _) => { };
24
25
  }
25
26
 
26
27
  [UnityTest]
@@ -39,23 +40,109 @@
39
40
  RunTest(component => NormalComponent(timer, timeout, component, message));
40
41
  RunTest(component => NoCopyGameObject(timer, timeout, component, message));
41
42
  RunTest(component => NoCopyComponent(timer, timeout, component, message));
42
-
43
+
43
44
  SimpleUntargetedMessage untargetedMessage = new();
44
45
  RunTest(component => NoCopyUntargeted(timer, timeout, component, untargetedMessage));
45
46
  yield break;
46
47
  }
47
48
 
49
+ [UnityTest]
50
+ [Performance]
51
+ public IEnumerator BenchmarkBroadcast()
52
+ {
53
+ GameObject go = CreateGameObject();
54
+ MessageRegistrationToken token = GetToken(
55
+ go.GetComponent<EmptyMessageAwareComponent>()
56
+ );
57
+ int count = 0;
58
+ token.RegisterGameObjectBroadcast<SimpleBroadcastMessage>(go, Handle);
59
+
60
+ SimpleBroadcastMessage message = new();
61
+
62
+ Measure
63
+ .Method(() => message.EmitGameObjectBroadcast(go))
64
+ .WarmupCount(10)
65
+ .IterationsPerMeasurement(10)
66
+ .MeasurementCount(1_000)
67
+ .Run();
68
+ yield break;
69
+
70
+ void Handle(SimpleBroadcastMessage _)
71
+ {
72
+ ++count;
73
+ }
74
+ }
75
+
76
+ [UnityTest]
77
+ [Performance]
78
+ public IEnumerator BenchmarkTargeted()
79
+ {
80
+ GameObject go = CreateGameObject();
81
+ MessageRegistrationToken token = GetToken(
82
+ go.GetComponent<EmptyMessageAwareComponent>()
83
+ );
84
+ int count = 0;
85
+ token.RegisterGameObjectTargeted<SimpleTargetedMessage>(go, Handle);
86
+
87
+ SimpleTargetedMessage message = new();
88
+
89
+ Measure
90
+ .Method(() => message.EmitGameObjectTargeted(go))
91
+ .WarmupCount(10)
92
+ .IterationsPerMeasurement(10)
93
+ .MeasurementCount(1_000)
94
+ .Run();
95
+ yield break;
96
+
97
+ void Handle(SimpleTargetedMessage _)
98
+ {
99
+ ++count;
100
+ }
101
+ }
102
+
103
+ [UnityTest]
104
+ [Performance]
105
+ public IEnumerator BenchmarkUntargeted()
106
+ {
107
+ GameObject go = CreateGameObject();
108
+ MessageRegistrationToken token = GetToken(
109
+ go.GetComponent<EmptyMessageAwareComponent>()
110
+ );
111
+ int count = 0;
112
+ token.RegisterUntargeted<SimpleUntargetedMessage>(Handle);
113
+
114
+ SimpleUntargetedMessage message = new();
115
+
116
+ Measure
117
+ .Method(() => message.EmitUntargeted())
118
+ .WarmupCount(10)
119
+ .IterationsPerMeasurement(10)
120
+ .MeasurementCount(1_000)
121
+ .Run();
122
+ yield break;
123
+
124
+ void Handle(SimpleUntargetedMessage _)
125
+ {
126
+ ++count;
127
+ }
128
+ }
129
+
48
130
  private GameObject CreateGameObject()
49
131
  {
50
132
  GameObject target = new(
51
- nameof(Benchmark), typeof(EmptyMessageAwareComponent), typeof(SpriteRenderer),
52
- typeof(Rigidbody2D), typeof(CircleCollider2D), typeof(LineRenderer));
133
+ nameof(Benchmark),
134
+ typeof(EmptyMessageAwareComponent),
135
+ typeof(SpriteRenderer),
136
+ typeof(Rigidbody2D),
137
+ typeof(CircleCollider2D),
138
+ typeof(LineRenderer)
139
+ );
53
140
  _spawned.Add(target);
54
141
 
55
142
  return target;
56
143
  }
57
144
 
58
- private void DisplayCount(string testName, int count, TimeSpan timeout)
145
+ private static void DisplayCount(string testName, int count, TimeSpan timeout)
59
146
  {
60
147
  Debug.Log($"| {testName} | {Math.Floor(count / timeout.TotalSeconds):N0} |");
61
148
  }
@@ -74,7 +161,12 @@
74
161
  }
75
162
  }
76
163
 
77
- private void Unity(Stopwatch timer, TimeSpan timeout, GameObject target, ComplexTargetedMessage message)
164
+ private static void Unity(
165
+ Stopwatch timer,
166
+ TimeSpan timeout,
167
+ GameObject target,
168
+ ComplexTargetedMessage message
169
+ )
78
170
  {
79
171
  int count = 0;
80
172
  var component = target.AddComponent<SimpleMessageAwareComponent>();
@@ -82,13 +174,20 @@
82
174
  timer.Restart();
83
175
  do
84
176
  {
85
- target.SendMessage(nameof(SimpleMessageAwareComponent.HandleSlowComplexTargetedMessage), message);
86
- }
87
- while (timer.Elapsed < timeout);
177
+ target.SendMessage(
178
+ nameof(SimpleMessageAwareComponent.HandleSlowComplexTargetedMessage),
179
+ message
180
+ );
181
+ } while (timer.Elapsed < timeout);
88
182
  DisplayCount("Unity", count, timeout);
89
183
  }
90
184
 
91
- private void NormalGameObject(Stopwatch timer, TimeSpan timeout, EmptyMessageAwareComponent component, ComplexTargetedMessage message)
185
+ private void NormalGameObject(
186
+ Stopwatch timer,
187
+ TimeSpan timeout,
188
+ EmptyMessageAwareComponent component,
189
+ ComplexTargetedMessage message
190
+ )
92
191
  {
93
192
  int count = 0;
94
193
  var token = GetToken(component);
@@ -104,12 +203,16 @@
104
203
  do
105
204
  {
106
205
  message.EmitGameObjectTargeted(go);
107
- }
108
- while (timer.Elapsed < timeout);
206
+ } while (timer.Elapsed < timeout);
109
207
  DisplayCount("DxMessaging (GameObject) - Normal", count, timeout);
110
208
  }
111
209
 
112
- private void NormalComponent(Stopwatch timer, TimeSpan timeout, EmptyMessageAwareComponent component, ComplexTargetedMessage message)
210
+ private void NormalComponent(
211
+ Stopwatch timer,
212
+ TimeSpan timeout,
213
+ EmptyMessageAwareComponent component,
214
+ ComplexTargetedMessage message
215
+ )
113
216
  {
114
217
  int count = 0;
115
218
  var token = GetToken(component);
@@ -124,12 +227,16 @@
124
227
  do
125
228
  {
126
229
  message.EmitComponentTargeted(component);
127
- }
128
- while (timer.Elapsed < timeout);
230
+ } while (timer.Elapsed < timeout);
129
231
  DisplayCount("DxMessaging (Component) - Normal", count, timeout);
130
232
  }
131
233
 
132
- private void NoCopyGameObject(Stopwatch timer, TimeSpan timeout, EmptyMessageAwareComponent component, ComplexTargetedMessage message)
234
+ private void NoCopyGameObject(
235
+ Stopwatch timer,
236
+ TimeSpan timeout,
237
+ EmptyMessageAwareComponent component,
238
+ ComplexTargetedMessage message
239
+ )
133
240
  {
134
241
  int count = 0;
135
242
  var token = GetToken(component);
@@ -146,12 +253,16 @@
146
253
  do
147
254
  {
148
255
  message.EmitGameObjectTargeted(component.gameObject);
149
- }
150
- while (timer.Elapsed < timeout);
256
+ } while (timer.Elapsed < timeout);
151
257
  DisplayCount("DxMessaging (GameObject) - No-Copy", count, timeout);
152
258
  }
153
259
 
154
- private void NoCopyComponent(Stopwatch timer, TimeSpan timeout, EmptyMessageAwareComponent component, ComplexTargetedMessage message)
260
+ private void NoCopyComponent(
261
+ Stopwatch timer,
262
+ TimeSpan timeout,
263
+ EmptyMessageAwareComponent component,
264
+ ComplexTargetedMessage message
265
+ )
155
266
  {
156
267
  int count = 0;
157
268
  var token = GetToken(component);
@@ -167,12 +278,16 @@
167
278
  do
168
279
  {
169
280
  message.EmitComponentTargeted(component);
170
- }
171
- while (timer.Elapsed < timeout);
281
+ } while (timer.Elapsed < timeout);
172
282
  DisplayCount("DxMessaging (Component) - No-Copy", count, timeout);
173
283
  }
174
284
 
175
- private void NoCopyUntargeted(Stopwatch timer, TimeSpan timeout, EmptyMessageAwareComponent component, SimpleUntargetedMessage message)
285
+ private void NoCopyUntargeted(
286
+ Stopwatch timer,
287
+ TimeSpan timeout,
288
+ EmptyMessageAwareComponent component,
289
+ SimpleUntargetedMessage message
290
+ )
176
291
  {
177
292
  int count = 0;
178
293
  var token = GetToken(component);
@@ -188,9 +303,8 @@
188
303
  do
189
304
  {
190
305
  message.EmitUntargeted();
191
- }
192
- while (timer.Elapsed < timeout);
306
+ } while (timer.Elapsed < timeout);
193
307
  DisplayCount("DxMessaging (Untargeted) - No-Copy", count, timeout);
194
308
  }
195
309
  }
196
- }
310
+ }
@@ -727,6 +727,10 @@
727
727
  {
728
728
  Assert.AreEqual(previous + 1, received[priority - 1]);
729
729
  }
730
+ for (int j = priority + 1; j < received.Length; ++j)
731
+ {
732
+ Assert.AreEqual(previous, received[j]);
733
+ }
730
734
  },
731
735
  priority: priority
732
736
  );
@@ -740,6 +744,10 @@
740
744
  {
741
745
  Assert.AreEqual(previous + 1, received[priority - 1]);
742
746
  }
747
+ for (int j = priority + 1; j < received.Length; ++j)
748
+ {
749
+ Assert.AreEqual(previous, received[j]);
750
+ }
743
751
  },
744
752
  priority: priority
745
753
  );
@@ -786,9 +794,13 @@
786
794
  (ref SimpleBroadcastMessage _) =>
787
795
  {
788
796
  int previous = received[priority]++;
789
- if (0 < priority)
797
+ for (int j = priority - 1; j >= 0; --j)
790
798
  {
791
- Assert.AreEqual(previous + 1, received[priority - 1]);
799
+ Assert.AreEqual(previous + 1, received[j]);
800
+ }
801
+ for (int j = priority + 1; j < received.Length; ++j)
802
+ {
803
+ Assert.AreEqual(previous, received[j]);
792
804
  }
793
805
  },
794
806
  priority: priority
@@ -799,9 +811,14 @@
799
811
  {
800
812
  int previous = received[priority]++;
801
813
  Assert.AreEqual(1, previous % 2);
802
- if (0 < priority)
814
+ for (int j = priority - 1; j >= 0; --j)
803
815
  {
804
- Assert.AreEqual(previous + 1, received[priority - 1]);
816
+ Assert.AreEqual(previous + 1, received[j]);
817
+ }
818
+
819
+ for (int j = priority + 1; j < received.Length; ++j)
820
+ {
821
+ Assert.AreEqual(previous, received[j]);
805
822
  }
806
823
  },
807
824
  priority: priority
@@ -828,5 +845,55 @@
828
845
  Assert.AreEqual(numRuns * 2, received.Distinct().Single());
829
846
  yield break;
830
847
  }
848
+
849
+ [UnityTest]
850
+ public IEnumerator Interceptor()
851
+ {
852
+ GameObject test = new(nameof(Interceptor), typeof(EmptyMessageAwareComponent));
853
+ _spawned.Add(test);
854
+
855
+ int[] received = new int[100];
856
+ EmptyMessageAwareComponent component = test.GetComponent<EmptyMessageAwareComponent>();
857
+ MessageRegistrationToken token = GetToken(component);
858
+ for (int i = 0; i < received.Length; ++i)
859
+ {
860
+ int priority = i;
861
+ token.RegisterBroadcastInterceptor(
862
+ (ref InstanceId source, ref SimpleBroadcastMessage _) =>
863
+ {
864
+ int previous = received[priority]++;
865
+ for (int j = priority - 1; j >= 0; --j)
866
+ {
867
+ Assert.AreEqual(previous + 1, received[j]);
868
+ }
869
+ for (int j = priority + 1; j < received.Length; ++j)
870
+ {
871
+ Assert.AreEqual(previous, received[j]);
872
+ }
873
+
874
+ return true;
875
+ },
876
+ priority: priority
877
+ );
878
+ }
879
+
880
+ SimpleBroadcastMessage message = new();
881
+ const int numRuns = 100;
882
+ for (int i = 0; i < numRuns; ++i)
883
+ {
884
+ message.EmitComponentBroadcast(component);
885
+ message.EmitGameObjectBroadcast(test);
886
+ }
887
+
888
+ Assert.AreEqual(
889
+ 1,
890
+ received.Distinct().Count(),
891
+ "Expected received to be uniform, found: [{0}].",
892
+ string.Join(",", received.Distinct().OrderBy(x => x))
893
+ );
894
+
895
+ Assert.AreEqual(numRuns * 2, received.Distinct().Single());
896
+ yield break;
897
+ }
831
898
  }
832
899
  }
@@ -713,9 +713,13 @@
713
713
  (ref SimpleTargetedMessage _) =>
714
714
  {
715
715
  int previous = received[priority]++;
716
- if (0 < priority)
716
+ for (int j = priority - 1; j >= 0; --j)
717
717
  {
718
- Assert.AreEqual(previous + 1, received[priority - 1]);
718
+ Assert.AreEqual(previous + 1, received[j]);
719
+ }
720
+ for (int j = priority + 1; j < received.Length; ++j)
721
+ {
722
+ Assert.AreEqual(previous, received[j]);
719
723
  }
720
724
  },
721
725
  priority: priority
@@ -726,9 +730,13 @@
726
730
  {
727
731
  int previous = received[priority]++;
728
732
  Assert.AreEqual(1, previous % 2);
729
- if (0 < priority)
733
+ for (int j = priority - 1; j >= 0; --j)
734
+ {
735
+ Assert.AreEqual(previous + 1, received[j]);
736
+ }
737
+ for (int j = priority + 1; j < received.Length; ++j)
730
738
  {
731
- Assert.AreEqual(previous + 1, received[priority - 1]);
739
+ Assert.AreEqual(previous, received[j]);
732
740
  }
733
741
  },
734
742
  priority: priority
@@ -776,9 +784,13 @@
776
784
  (ref SimpleTargetedMessage _) =>
777
785
  {
778
786
  int previous = received[priority]++;
779
- if (0 < priority)
787
+ for (int j = priority - 1; j >= 0; --j)
780
788
  {
781
- Assert.AreEqual(previous + 1, received[priority - 1]);
789
+ Assert.AreEqual(previous + 1, received[j]);
790
+ }
791
+ for (int j = priority + 1; j < received.Length; ++j)
792
+ {
793
+ Assert.AreEqual(previous, received[j]);
782
794
  }
783
795
  },
784
796
  priority: priority
@@ -789,9 +801,13 @@
789
801
  {
790
802
  int previous = received[priority]++;
791
803
  Assert.AreEqual(1, previous % 2);
792
- if (0 < priority)
804
+ for (int j = priority - 1; j >= 0; --j)
793
805
  {
794
- Assert.AreEqual(previous + 1, received[priority - 1]);
806
+ Assert.AreEqual(previous + 1, received[j]);
807
+ }
808
+ for (int j = priority + 1; j < received.Length; ++j)
809
+ {
810
+ Assert.AreEqual(previous, received[j]);
795
811
  }
796
812
  },
797
813
  priority: priority
@@ -818,5 +834,55 @@
818
834
  Assert.AreEqual(numRuns * 2, received.Distinct().Single());
819
835
  yield break;
820
836
  }
837
+
838
+ [UnityTest]
839
+ public IEnumerator Interceptor()
840
+ {
841
+ GameObject test = new(nameof(Interceptor), typeof(EmptyMessageAwareComponent));
842
+ _spawned.Add(test);
843
+
844
+ int[] received = new int[100];
845
+ EmptyMessageAwareComponent component = test.GetComponent<EmptyMessageAwareComponent>();
846
+ MessageRegistrationToken token = GetToken(component);
847
+ for (int i = 0; i < received.Length; ++i)
848
+ {
849
+ int priority = i;
850
+ token.RegisterTargetedInterceptor(
851
+ (ref InstanceId source, ref SimpleTargetedMessage _) =>
852
+ {
853
+ int previous = received[priority]++;
854
+ for (int j = priority - 1; j >= 0; --j)
855
+ {
856
+ Assert.AreEqual(previous + 1, received[j]);
857
+ }
858
+ for (int j = priority + 1; j < received.Length; ++j)
859
+ {
860
+ Assert.AreEqual(previous, received[j]);
861
+ }
862
+
863
+ return true;
864
+ },
865
+ priority: priority
866
+ );
867
+ }
868
+
869
+ SimpleTargetedMessage message = new();
870
+ const int numRuns = 100;
871
+ for (int i = 0; i < numRuns; ++i)
872
+ {
873
+ message.EmitComponentTargeted(component);
874
+ message.EmitGameObjectTargeted(test);
875
+ }
876
+
877
+ Assert.AreEqual(
878
+ 1,
879
+ received.Distinct().Count(),
880
+ "Expected received to be uniform, found: [{0}].",
881
+ string.Join(",", received.Distinct().OrderBy(x => x))
882
+ );
883
+
884
+ Assert.AreEqual(numRuns * 2, received.Distinct().Single());
885
+ yield break;
886
+ }
821
887
  }
822
888
  }
@@ -172,9 +172,13 @@
172
172
  (ref SimpleUntargetedMessage _) =>
173
173
  {
174
174
  int previous = received[priority]++;
175
- if (0 < priority)
175
+ for (int j = priority - 1; j >= 0; --j)
176
176
  {
177
- Assert.AreEqual(previous + 1, received[priority - 1]);
177
+ Assert.AreEqual(previous + 1, received[j]);
178
+ }
179
+ for (int j = priority + 1; j < received.Length; ++j)
180
+ {
181
+ Assert.AreEqual(previous, received[j]);
178
182
  }
179
183
  },
180
184
  priority: priority
@@ -184,9 +188,13 @@
184
188
  {
185
189
  int previous = received[priority]++;
186
190
  Assert.AreEqual(1, previous % 2);
187
- if (0 < priority)
191
+ for (int j = priority - 1; j >= 0; --j)
192
+ {
193
+ Assert.AreEqual(previous + 1, received[j]);
194
+ }
195
+ for (int j = priority + 1; j < received.Length; ++j)
188
196
  {
189
- Assert.AreEqual(previous + 1, received[priority - 1]);
197
+ Assert.AreEqual(previous, received[j]);
190
198
  }
191
199
  },
192
200
  priority: priority
@@ -211,5 +219,54 @@
211
219
  Assert.AreEqual(numRuns * 2, received.Distinct().Single());
212
220
  yield break;
213
221
  }
222
+
223
+ [UnityTest]
224
+ public IEnumerator Interceptor()
225
+ {
226
+ GameObject test = new(nameof(Interceptor), typeof(EmptyMessageAwareComponent));
227
+ _spawned.Add(test);
228
+
229
+ int[] received = new int[100];
230
+ EmptyMessageAwareComponent component = test.GetComponent<EmptyMessageAwareComponent>();
231
+ MessageRegistrationToken token = GetToken(component);
232
+ for (int i = 0; i < received.Length; ++i)
233
+ {
234
+ int priority = i;
235
+ token.RegisterUntargetedInterceptor(
236
+ (ref SimpleUntargetedMessage _) =>
237
+ {
238
+ int previous = received[priority]++;
239
+ for (int j = priority - 1; j >= 0; --j)
240
+ {
241
+ Assert.AreEqual(previous + 1, received[j]);
242
+ }
243
+ for (int j = priority + 1; j < received.Length; ++j)
244
+ {
245
+ Assert.AreEqual(previous, received[j]);
246
+ }
247
+
248
+ return true;
249
+ },
250
+ priority: priority
251
+ );
252
+ }
253
+
254
+ SimpleUntargetedMessage message = new();
255
+ const int numRuns = 100;
256
+ for (int i = 0; i < numRuns; ++i)
257
+ {
258
+ message.EmitUntargeted();
259
+ }
260
+
261
+ Assert.AreEqual(
262
+ 1,
263
+ received.Distinct().Count(),
264
+ "Expected received to be uniform, found: [{0}].",
265
+ string.Join(",", received.Distinct().OrderBy(x => x))
266
+ );
267
+
268
+ Assert.AreEqual(numRuns, received.Distinct().Single());
269
+ yield break;
270
+ }
214
271
  }
215
272
  }
@@ -4,7 +4,8 @@
4
4
  "references": [
5
5
  "UnityEngine.TestRunner",
6
6
  "UnityEditor.TestRunner",
7
- "WallstopStudios.DxMessaging"
7
+ "WallstopStudios.DxMessaging",
8
+ "Unity.PerformanceTesting"
8
9
  ],
9
10
  "includePlatforms": [],
10
11
  "excludePlatforms": [],
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "com.wallstop-studios.dxmessaging",
3
- "version": "2.0.0-rc07",
3
+ "version": "2.0.0-rc08",
4
4
  "displayName": "DxMessaging",
5
5
  "description": "Synchronous Event Bus for Unity",
6
6
  "unity": "2021.3",
7
7
  "dependencies": {
8
- "com.wallstop-studios.unity-helpers" : "2.0.0-rc04"
8
+ "com.wallstop-studios.unity-helpers" : "2.0.0-rc13"
9
9
  },
10
10
  "keywords": [
11
11
  "messaging",
package/Tests/Editor.meta DELETED
@@ -1,8 +0,0 @@
1
- fileFormatVersion: 2
2
- guid: 2f8663039d4ca4f43a9acdf5f22e30ed
3
- folderAsset: yes
4
- DefaultImporter:
5
- externalObjects: {}
6
- userData:
7
- assetBundleName:
8
- assetBundleVariant: