From 7cecd20d8d593506af5f49e9689a4ae2c206a477 Mon Sep 17 00:00:00 2001 From: goyuken Date: Wed, 17 Dec 2014 01:17:41 +0000 Subject: [PATCH] restore large speed regression on NESHawk core from r8379. other managed cores were likely affected. most managed cores not affected because of event tracking... --- .../MemoryCallbackSystem.cs | 142 ++++++++++-------- 1 file changed, 81 insertions(+), 61 deletions(-) diff --git a/BizHawk.Emulation.Common/Base Implementations/MemoryCallbackSystem.cs b/BizHawk.Emulation.Common/Base Implementations/MemoryCallbackSystem.cs index 9ca678f7d5..052a191b58 100644 --- a/BizHawk.Emulation.Common/Base Implementations/MemoryCallbackSystem.cs +++ b/BizHawk.Emulation.Common/Base Implementations/MemoryCallbackSystem.cs @@ -8,120 +8,140 @@ namespace BizHawk.Emulation.Common { public class MemoryCallbackSystem : IMemoryCallbackSystem { - private readonly List Callbacks = new List(); + private readonly List Reads = new List(); + private readonly List Writes = new List(); + private readonly List Execs = new List(); - public IEnumerator GetEnumerator() - { - return Callbacks.GetEnumerator(); - } - - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } + bool empty = true; public void Add(IMemoryCallback callback) { - var hadAny = Callbacks.Any(); + switch (callback.Type) + { + case MemoryCallbackType.Execute: Execs.Add(callback); break; + case MemoryCallbackType.Read: Reads.Add(callback); break; + case MemoryCallbackType.Write: Writes.Add(callback); break; + } + if (empty) + Changes(); + empty = false; + } - Callbacks.Add(callback); - - var hasAny = Callbacks.Any(); - Changes(hadAny, hasAny); + private static void Call(List cbs, uint addr) + { + for (int i = 0; i < cbs.Count; i++) + { + if (!cbs[i].Address.HasValue || cbs[i].Address == addr) + cbs[i].Callback(); + } } public void CallReads(uint addr) { - foreach (var read in Callbacks.Where(callback => callback.Type == MemoryCallbackType.Read)) - { - if (!read.Address.HasValue || read.Address == addr) - { - read.Callback(); - } - } + Call(Reads, addr); } public void CallWrites(uint addr) { - foreach (var read in Callbacks.Where(callback => callback.Type == MemoryCallbackType.Write)) - { - if (!read.Address.HasValue || read.Address == addr) - { - read.Callback(); - } - } + Call(Writes, addr); } public void CallExecutes(uint addr) { - foreach (var read in Callbacks.Where(callback => callback.Type == MemoryCallbackType.Execute)) - { - if (!read.Address.HasValue || read.Address == addr) - { - read.Callback(); - } - } + Call(Execs, addr); } public bool HasReads { - get { return Callbacks.Any(callback => callback.Type == MemoryCallbackType.Read); } + get { return Reads.Count > 0; } } public bool HasWrites { - get { return Callbacks.Any(callback => callback.Type == MemoryCallbackType.Write); } + get { return Writes.Count > 0; } } public bool HasExecutes { - get { return Callbacks.Any(callback => callback.Type == MemoryCallbackType.Execute); } + get { return Execs.Count > 0; } + } + + private int RemoveInternal(Action action) + { + int ret = 0; + ret += Reads.RemoveAll(imc => imc.Callback == action); + ret += Writes.RemoveAll(imc => imc.Callback == action); + ret += Execs.RemoveAll(imc => imc.Callback == action); + return ret; } public void Remove(Action action) { - var hadAny = Callbacks.Any(); - - var actions = Callbacks.Where(c => c.Callback == action); - Callbacks.RemoveAll(c => actions.Contains(c)); - - var hasAny = Callbacks.Any(); - Changes(hadAny, hasAny); + if (RemoveInternal(action) > 0) + { + bool newEmpty = !HasReads && !HasWrites && !HasExecutes; + if (newEmpty != empty) + Changes(); + empty = newEmpty; + } } public void RemoveAll(IEnumerable actions) { - var hadAny = Callbacks.Any(); - + bool changed = false; foreach (var action in actions) { - Remove(action); + changed |= RemoveInternal(action) > 0; + } + if (changed) + { + bool newEmpty = !HasReads && !HasWrites && !HasExecutes; + if (newEmpty != empty) + Changes(); + empty = newEmpty; } - - var hasAny = Callbacks.Any(); - Changes(hadAny, hasAny); } public void Clear() { - var hadAny = Callbacks.Any(); - Callbacks.Clear(); - Changes(hadAny, false); + Reads.Clear(); + Writes.Clear(); + Execs.Clear(); + if (!empty) + Changes(); + empty = true; } public delegate void ActiveChangedEventHandler(); public event ActiveChangedEventHandler ActiveChanged; - private void Changes(bool hadAny, bool hasAny) + private void Changes() { - if ((hadAny && !hasAny) || (!hadAny && hasAny)) + if (ActiveChanged != null) { - if (ActiveChanged != null) - { - ActiveChanged(); - } + ActiveChanged(); } } + + public IEnumerator GetEnumerator() + { + foreach (var imc in Reads) + yield return imc; + foreach (var imc in Writes) + yield return imc; + foreach (var imc in Execs) + yield return imc; + } + + IEnumerator IEnumerable.GetEnumerator() + { + foreach (var imc in Reads) + yield return imc; + foreach (var imc in Writes) + yield return imc; + foreach (var imc in Execs) + yield return imc; + } } public class MemoryCallback : IMemoryCallback