diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerRegionsProvider.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerRegionsProvider.java index a88772abe8..b8df73ce10 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerRegionsProvider.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerRegionsProvider.java @@ -33,11 +33,11 @@ import docking.WindowPosition; import docking.action.*; import docking.widgets.table.CustomToStringCellRenderer; import docking.widgets.table.DefaultEnumeratedColumnTableModel.EnumeratedTableColumn; -import docking.widgets.table.RowWrappedEnumeratedColumnTableModel; import ghidra.app.plugin.core.debug.DebuggerPluginPackage; import ghidra.app.plugin.core.debug.gui.DebuggerResources; import ghidra.app.plugin.core.debug.gui.DebuggerResources.AbstractSelectAddressesAction; import ghidra.app.plugin.core.debug.gui.DebuggerResources.SelectRowsAction; +import ghidra.app.plugin.core.debug.utils.DebouncedRowWrappedEnumeratedColumnTableModel; import ghidra.app.services.DebuggerListingService; import ghidra.app.services.DebuggerTraceManagerService; import ghidra.framework.model.DomainObject; @@ -115,7 +115,7 @@ public class DebuggerRegionsProvider extends ComponentProviderAdapter { } protected static class RegionTableModel - extends RowWrappedEnumeratedColumnTableModel< // + extends DebouncedRowWrappedEnumeratedColumnTableModel< // RegionTableColumns, ObjectKey, RegionRow, TraceMemoryRegion> { public RegionTableModel() { diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/modules/DebuggerModulesProvider.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/modules/DebuggerModulesProvider.java index c16200de23..2739c74d41 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/modules/DebuggerModulesProvider.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/modules/DebuggerModulesProvider.java @@ -34,14 +34,16 @@ import docking.ActionContext; import docking.WindowPosition; import docking.action.*; import docking.widgets.filechooser.GhidraFileChooser; -import docking.widgets.table.*; +import docking.widgets.table.CustomToStringCellRenderer; import docking.widgets.table.DefaultEnumeratedColumnTableModel.EnumeratedTableColumn; +import docking.widgets.table.TableFilter; import ghidra.app.plugin.core.debug.DebuggerPluginPackage; import ghidra.app.plugin.core.debug.gui.DebuggerResources; import ghidra.app.plugin.core.debug.gui.DebuggerResources.*; import ghidra.app.plugin.core.debug.service.modules.MapModulesBackgroundCommand; import ghidra.app.plugin.core.debug.service.modules.MapSectionsBackgroundCommand; import ghidra.app.plugin.core.debug.utils.BackgroundUtils; +import ghidra.app.plugin.core.debug.utils.DebouncedRowWrappedEnumeratedColumnTableModel; import ghidra.app.services.*; import ghidra.app.services.DebuggerStaticMappingService.*; import ghidra.async.AsyncUtils; @@ -200,7 +202,7 @@ public class DebuggerModulesProvider extends ComponentProviderAdapter { } protected static class ModuleTableModel - extends RowWrappedEnumeratedColumnTableModel< // + extends DebouncedRowWrappedEnumeratedColumnTableModel< // ModuleTableColumns, ObjectKey, ModuleRow, TraceModule> { public ModuleTableModel() { @@ -209,7 +211,7 @@ public class DebuggerModulesProvider extends ComponentProviderAdapter { } protected static class SectionTableModel - extends RowWrappedEnumeratedColumnTableModel< // + extends DebouncedRowWrappedEnumeratedColumnTableModel< // SectionTableColumns, ObjectKey, SectionRow, TraceSection> { public SectionTableModel() { diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/modules/DebuggerStaticMappingProvider.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/modules/DebuggerStaticMappingProvider.java index 86654ba458..b6b604c5e5 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/modules/DebuggerStaticMappingProvider.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/modules/DebuggerStaticMappingProvider.java @@ -32,12 +32,14 @@ import com.google.common.collect.Range; import docking.ActionContext; import docking.action.DockingAction; import docking.action.DockingActionIf; -import docking.widgets.table.*; +import docking.widgets.table.CustomToStringCellRenderer; import docking.widgets.table.DefaultEnumeratedColumnTableModel.EnumeratedTableColumn; +import docking.widgets.table.GTable; import ghidra.app.plugin.core.debug.DebuggerPluginPackage; import ghidra.app.plugin.core.debug.gui.DebuggerProvider; import ghidra.app.plugin.core.debug.gui.DebuggerResources; import ghidra.app.plugin.core.debug.gui.DebuggerResources.*; +import ghidra.app.plugin.core.debug.utils.DebouncedRowWrappedEnumeratedColumnTableModel; import ghidra.app.services.*; import ghidra.framework.model.DomainObject; import ghidra.framework.plugintool.AutoService; @@ -98,7 +100,7 @@ public class DebuggerStaticMappingProvider extends ComponentProviderAdapter } protected static class MappingTableModel - extends RowWrappedEnumeratedColumnTableModel< // + extends DebouncedRowWrappedEnumeratedColumnTableModel< // StaticMappingTableColumns, ObjectKey, StaticMappingRow, TraceStaticMapping> { public MappingTableModel() { diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/objects/ObjectContainer.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/objects/ObjectContainer.java index 880d9596c3..94c1e37734 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/objects/ObjectContainer.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/objects/ObjectContainer.java @@ -156,7 +156,7 @@ public class ObjectContainer implements Comparable { if (targetObject == null) { return CompletableFuture.completedFuture(null); } - return targetObject.resync(true, true).thenApply(__ -> { + return targetObject.resync(true, true).thenApplyAsync(__ -> { rebuildContainers(targetObject.getCachedElements(), targetObject.getCachedAttributes()); propagateProvider(provider); return this; diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/utils/DebouncedRowWrappedEnumeratedColumnTableModel.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/utils/DebouncedRowWrappedEnumeratedColumnTableModel.java new file mode 100644 index 0000000000..ab086ea131 --- /dev/null +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/utils/DebouncedRowWrappedEnumeratedColumnTableModel.java @@ -0,0 +1,69 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package ghidra.app.plugin.core.debug.utils; + +import java.util.function.Function; + +import docking.widgets.table.DefaultEnumeratedColumnTableModel.EnumeratedTableColumn; +import docking.widgets.table.RowWrappedEnumeratedColumnTableModel; +import ghidra.async.AsyncDebouncer; +import ghidra.async.AsyncTimer; +import ghidra.util.Swing; + +public class DebouncedRowWrappedEnumeratedColumnTableModel & EnumeratedTableColumn, K, R, T> + extends RowWrappedEnumeratedColumnTableModel { + + AsyncDebouncer debouncer = new AsyncDebouncer(AsyncTimer.DEFAULT_TIMER, 100); + + public DebouncedRowWrappedEnumeratedColumnTableModel(String name, Class colType, + Function keyFunc, Function wrapper) { + super(name, colType, keyFunc, wrapper); + + debouncer.addListener(this::settled); + } + + @Override + public void fireTableDataChanged() { + debouncer.contact(null); + } + + @Override + public void fireTableCellUpdated(int row, int column) { + debouncer.contact(null); + } + + @Override + public void fireTableRowsDeleted(int firstRow, int lastRow) { + debouncer.contact(null); + } + + @Override + public void fireTableRowsInserted(int firstRow, int lastRow) { + debouncer.contact(null); + } + + @Override + public void fireTableRowsUpdated(int firstRow, int lastRow) { + debouncer.contact(null); + } + + // NB. Let structure changes get processed immediately + + private void settled(Void __) { + // Just refresh the whole thing + Swing.runLater(() -> super.fireTableDataChanged()); + } +} diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/util/DefaultTraceTimeViewport.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/util/DefaultTraceTimeViewport.java index de20b391b8..2d11744655 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/util/DefaultTraceTimeViewport.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/util/DefaultTraceTimeViewport.java @@ -22,7 +22,6 @@ import java.util.stream.Collectors; import com.google.common.collect.*; import ghidra.framework.model.DomainObjectClosedListener; -import ghidra.framework.model.DomainObjectException; import ghidra.program.model.address.*; import ghidra.trace.model.Trace; import ghidra.trace.model.Trace.TraceSnapshotChangeType; @@ -31,7 +30,6 @@ import ghidra.trace.model.program.TraceProgramView; import ghidra.trace.model.time.*; import ghidra.util.*; import ghidra.util.datastruct.ListenerSet; -import ghidra.util.exception.ClosedException; /** * Computes and tracks the "viewport" resulting from forking patterns encoded in snapshot schedules @@ -93,7 +91,7 @@ public class DefaultTraceTimeViewport implements TraceTimeViewport { protected final Trace trace; protected final TraceTimeManager timeManager; - protected final List> ordered = new ArrayList<>(); + protected final List> ordered = Collections.synchronizedList(new ArrayList<>()); protected final RangeSet spanSet = TreeRangeSet.create(); protected final ForSnapshotsListener listener = new ForSnapshotsListener(); protected final ListenerSet changeListeners = new ListenerSet<>(Runnable.class);