|
6 | 6 | using System.Collections.Generic;
|
7 | 7 | using System.Collections.ObjectModel;
|
8 | 8 | using System.Collections.Specialized;
|
| 9 | +using System.Diagnostics; |
9 | 10 |
|
10 | 11 | namespace BizHawk.Emulation.Common
|
11 | 12 | {
|
@@ -67,15 +68,38 @@ public void Add(IMemoryCallback callback)
|
67 | 68 |
|
68 | 69 | private static void Call(ObservableCollection<IMemoryCallback> cbs, uint addr, uint value, uint flags, string scope)
|
69 | 70 | {
|
70 |
| - // ReSharper disable once ForCanBeConvertedToForeach |
71 |
| - // Intentionally a for loop - https://github.com/TASEmulators/BizHawk/issues/1823 |
72 |
| - for (int i = 0; i < cbs.Count; i++) |
| 71 | + var cbsCopy = cbs.ToArray(); |
| 72 | + var e = cbsCopy.Length; |
| 73 | + var i = -1; |
| 74 | + void UpdateIndexAndEndpoint(object _, NotifyCollectionChangedEventArgs args) |
73 | 75 | {
|
74 |
| - if (!cbs[i].Address.HasValue || (cbs[i].Scope == scope && cbs[i].Address == (addr & cbs[i].AddressMask))) |
| 76 | + // this was helpful: https://www.codeproject.com/Articles/1004644/ObservableCollection-Simply-Explained |
| 77 | + switch (args.Action) |
75 | 78 | {
|
76 |
| - cbs[i].Callback(addr, value, flags); |
| 79 | + case NotifyCollectionChangedAction.Add: |
| 80 | + Debug.Assert(args.NewStartingIndex >= e); |
| 81 | + // no-op |
| 82 | + break; |
| 83 | + case NotifyCollectionChangedAction.Remove: |
| 84 | + Debug.Assert(args.OldItems.Count is 1); |
| 85 | + e--; |
| 86 | + if (args.OldStartingIndex <= i) i--; // if ==, i will be decremented and incremented, so it ends up pointing to the element which was at i + 1, now at i |
| 87 | + break; |
| 88 | + default: |
| 89 | + Debug.WriteLine("Unexpected operation on memory callback collection!"); |
| 90 | + break; |
77 | 91 | }
|
78 | 92 | }
|
| 93 | + cbs.CollectionChanged += UpdateIndexAndEndpoint; |
| 94 | + while (++i < e) |
| 95 | + { |
| 96 | + var cb = cbsCopy[i]; |
| 97 | + if (!cb.Address.HasValue || (cb.Scope == scope && cb.Address == (addr & cb.AddressMask))) |
| 98 | + { |
| 99 | + cb.Callback(addr, value, flags); |
| 100 | + } |
| 101 | + } |
| 102 | + cbs.CollectionChanged -= UpdateIndexAndEndpoint; |
79 | 103 | }
|
80 | 104 |
|
81 | 105 | public void CallMemoryCallbacks(uint addr, uint value, uint flags, string scope)
|
|
0 commit comments