GT-2875 - Unswingable - review fixes

This commit is contained in:
dragonmacher 2019-05-21 14:51:32 -04:00
parent 5e8340b7f8
commit 31f3cca1a5
27 changed files with 100 additions and 79 deletions

View file

@ -26,10 +26,10 @@ import docking.action.DockingAction;
import docking.action.ToolBarData;
import docking.widgets.OptionDialog;
import ghidra.framework.plugintool.ComponentProviderAdapter;
import ghidra.generic.function.Callback;
import ghidra.util.HelpLocation;
import resources.Icons;
import resources.ResourceManager;
import utility.function.Callback;
public class InterpreterComponentProvider extends ComponentProviderAdapter
implements InterpreterConsole {

View file

@ -18,8 +18,8 @@ package ghidra.app.plugin.core.interpreter;
import java.io.*;
import docking.action.DockingAction;
import ghidra.generic.function.Callback;
import ghidra.util.Disposable;
import utility.function.Callback;
/**
* Interactive interpreter console.

View file

@ -33,7 +33,6 @@ import ghidra.app.nav.NavigatableRemovalListener;
import ghidra.app.services.GoToService;
import ghidra.app.util.HelpTopics;
import ghidra.framework.plugintool.PluginTool;
import ghidra.generic.function.Callback;
import ghidra.program.model.listing.Program;
import ghidra.program.util.ProgramLocation;
import ghidra.program.util.ProgramSelection;
@ -44,6 +43,7 @@ import ghidra.util.datastruct.WeakSet;
import ghidra.util.table.*;
import ghidra.util.task.TaskMonitor;
import resources.ResourceManager;
import utility.function.Callback;
/**
* Dialog to show a table of items. If the dialog is constructed with a non-null

View file

@ -49,7 +49,6 @@ import ghidra.app.context.ListingActionContext;
*/
import ghidra.app.services.DataTypeManagerService;
import ghidra.framework.plugintool.PluginTool;
import ghidra.generic.function.Callback;
import ghidra.program.database.symbol.EquateManager;
import ghidra.program.model.data.DataTypeManager;
import ghidra.program.model.data.Enum;
@ -62,6 +61,7 @@ import ghidra.util.UniversalID;
import ghidra.util.layout.HorizontalLayout;
import ghidra.util.layout.VerticalLayout;
import ghidra.util.table.*;
import utility.function.Callback;
public class SetEquateDialog extends DialogComponentProvider {
public static final int CANCELED = 0;

View file

@ -47,6 +47,7 @@ import ghidra.util.exception.AssertException;
import ghidra.util.exception.RollbackException;
import junit.framework.AssertionFailedError;
import utility.application.ApplicationLayout;
import utility.function.*;
public abstract class AbstractGhidraHeadlessIntegrationTest extends AbstractDockingTest {

View file

@ -25,13 +25,13 @@ import org.junit.After;
import ghidra.app.plugin.core.codebrowser.CodeBrowserPlugin;
import ghidra.framework.plugintool.PluginTool;
import ghidra.generic.function.ExceptionalConsumer;
import ghidra.generic.function.ExceptionalFunction;
import ghidra.program.model.address.*;
import ghidra.program.model.listing.*;
import ghidra.program.util.ProgramLocation;
import ghidra.util.exception.AssertException;
import util.CollectionUtils;
import utility.function.ExceptionalConsumer;
import utility.function.ExceptionalFunction;
/**
* A convenience base class for creating tests that use the default tool and open a program.

View file

@ -35,7 +35,6 @@ import ghidra.app.plugin.core.navigation.NextPrevAddressPlugin;
import ghidra.app.services.ProgramManager;
import ghidra.framework.plugintool.Plugin;
import ghidra.framework.plugintool.PluginTool;
import ghidra.generic.function.Callback;
import ghidra.program.database.ProgramBuilder;
import ghidra.program.model.address.*;
import ghidra.program.model.data.DataType;
@ -51,6 +50,7 @@ import ghidra.util.TrackedTaskListener;
import ghidra.util.table.GhidraTable;
import ghidra.util.table.field.AddressBasedLocation;
import ghidra.util.task.Task;
import utility.function.Callback;
public class AutoTableDisassemblerTest extends AbstractGhidraHeadedIntegrationTest {

View file

@ -32,10 +32,10 @@ import docking.event.mouse.GMouseListenerAdapter;
import docking.menu.DockingToolbarButton;
import docking.util.*;
import docking.widgets.label.GDHtmlLabel;
import ghidra.generic.function.Callback;
import ghidra.util.*;
import ghidra.util.exception.AssertException;
import ghidra.util.task.*;
import utility.function.Callback;
/**
* Base class used for creating dialogs in Ghidra. Subclass this to create a dialog provider that has

View file

@ -22,10 +22,10 @@ import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import ghidra.generic.function.Callback;
import ghidra.util.SystemUtilities;
import ghidra.util.datastruct.WeakDataStructureFactory;
import ghidra.util.datastruct.WeakSet;
import utility.function.Callback;
/**
* A text field that is meant to be used in conjunction with tables that allow filter text. This

View file

@ -28,10 +28,10 @@ import docking.widgets.filechooser.GhidraFileChooser;
import docking.widgets.filechooser.GhidraFileChooserMode;
import docking.widgets.table.*;
import ghidra.framework.preferences.Preferences;
import ghidra.generic.function.Callback;
import ghidra.util.filechooser.GhidraFileChooserModel;
import ghidra.util.filechooser.GhidraFileFilter;
import resources.ResourceManager;
import utility.function.Callback;
/**
* Component that has a table to show pathnames; the panel includes buttons to control

View file

@ -40,7 +40,6 @@ import docking.widgets.table.columnfilter.ColumnBasedTableFilter;
import docking.widgets.table.columnfilter.ColumnFilterSaveManager;
import docking.widgets.table.constraint.dialog.ColumnFilterDialog;
import ghidra.framework.options.PreferenceState;
import ghidra.generic.function.Callback;
import ghidra.util.HelpLocation;
import ghidra.util.Msg;
import ghidra.util.datastruct.WeakDataStructureFactory;
@ -50,6 +49,7 @@ import ghidra.util.task.SwingUpdateManager;
import resources.Icons;
import resources.ResourceManager;
import utilities.util.reflection.ReflectionUtilities;
import utility.function.Callback;
/**
* This class is a panel that provides a label and text field that allows users to input text that

View file

@ -33,11 +33,11 @@ import docking.widgets.table.GTableFilterPanel;
import docking.widgets.table.RowObjectFilterModel;
import docking.widgets.table.columnfilter.*;
import docking.widgets.table.constrainteditor.ColumnConstraintEditor;
import ghidra.generic.function.Callback;
import ghidra.util.HelpLocation;
import ghidra.util.Msg;
import ghidra.util.layout.VerticalLayout;
import resources.ResourceManager;
import utility.function.Callback;
/**
* Dialog for creating and editing column table filters.

View file

@ -176,8 +176,8 @@ public class TaskBuilder {
/**
* Sets the amount of time that will pass before showing the dialog. The default is
* {@link TaskLauncher#INITIAL_DELAY} for non-modal tasks and
* {@link TaskLauncher#INITIAL_MODAL_DELAY} for modal tasks.
* {@link TaskLauncher#INITIAL_DELAY_MS} for non-modal tasks and
* {@link TaskLauncher#INITIAL_MODAL_DELAY_MS} for modal tasks.
*
* @param delay the delay time
* @return this builder

View file

@ -23,13 +23,20 @@ import ghidra.util.exception.UnableToSwingException;
/**
* Class to initiate a Task in a new Thread, and to show a progress dialog that indicates
* activity. The progress dialog will show an animation in the event that the task of this class
* cannot show progress.
* activity <b>if the task takes too long</b>. The progress dialog will show an
* animation in the event that the task of this class cannot show progress.
*
* <p>For complete control of how this class functions, use
* {@link #TaskLauncher(Task, Component, int, int)}. Alternatively, for simpler uses,
* see one of the many static convenience methods.
*
* <p><b>Important Usage Note:</b><br>
* For clients that are not on the Swing thread the behavior of this class is designed to
* prevent deadlocks. When called from a non-Swing thread, this class will attempt to show a
* modal dialog. However, if more than {@link #getSwingTimeoutInSeconds()} elapses while waiting
* for the Swing thread, then this class will <b>give up on using the Swing thread and will not
* create a background thread</b>. Instead, the client code will be run in the client thread.
*
* <a name="modal_usage"></a>
* <p><b><a name="modal_usage">Modal Usage</a></b><br>
* Most clients of this class should not be concerned with where
@ -250,12 +257,12 @@ public class TaskLauncher {
Swing.runNow(() -> runner.run(), timeout, TimeUnit.SECONDS);
}
// template method to allow timeout change
// template method to allow timeout change; used by tests
protected int getSwingTimeoutInSeconds() {
return 2;
}
// template method to allow task runner change
// template method to allow task runner change; used by tests
protected TaskRunner createTaskRunner(Task task, Component parent, int delayMs,
int dialogWidth) {
return new TaskRunner(task, parent, delayMs, dialogWidth);

View file

@ -33,7 +33,7 @@ import org.junit.Before;
import org.junit.Test;
import generic.test.AbstractGenericTest;
import ghidra.generic.function.Callback;
import utility.function.Callback;
public class FilterTextFieldTest {

View file

@ -37,7 +37,7 @@ public class TaskUtilities {
}
/**
* Removes the given listener added via {@link #addTrackedTask(Task)}.
* Removes the given listener added via {@link #addTrackedTask(Task,TaskMonitor)}.
* @param listener The listener that needs to be removed.
*/
public static void removeTrackedTaskListener(TrackedTaskListener listener) {

View file

@ -19,12 +19,12 @@ import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import ghidra.generic.function.Callback;
import ghidra.util.SystemUtilities;
import ghidra.util.exception.CancelledException;
import ghidra.util.exception.TimeoutException;
import ghidra.util.timer.GTimer;
import ghidra.util.timer.GTimerMonitor;
import utility.function.Callback;
/**
* A task monitor that allows clients the ability to specify a timeout after which this monitor

View file

@ -24,12 +24,12 @@ import com.google.common.collect.Iterators;
import edu.uci.ics.jung.graph.util.EdgeType;
import edu.uci.ics.jung.graph.util.Pair;
import ghidra.generic.function.Callback;
import ghidra.graph.GraphAlgorithms;
import ghidra.graph.viewer.VisualEdge;
import ghidra.graph.viewer.VisualVertex;
import ghidra.graph.viewer.layout.VisualGraphLayout;
import util.CollectionUtils;
import utility.function.Callback;
/**
* A graph implementation that allows clients to mark vertices and edges as filtered. When

View file

@ -17,11 +17,11 @@ package ghidra.graph.job;
import java.util.*;
import ghidra.generic.function.Callback;
import ghidra.util.Msg;
import ghidra.util.SystemUtilities;
import ghidra.util.datastruct.QueueStub;
import ghidra.util.exception.AssertException;
import utility.function.Callback;
/**
* A class to run {@link GraphJob}s. This class will queue jobs and will run them

View file

@ -25,7 +25,6 @@ import java.util.Objects;
import com.google.common.base.Function;
import edu.uci.ics.jung.visualization.*;
import ghidra.generic.function.Callback;
import ghidra.graph.VisualGraph;
import ghidra.graph.job.*;
import ghidra.graph.viewer.edge.routing.BasicEdgeRouter;
@ -34,6 +33,7 @@ import ghidra.util.datastruct.WeakDataStructureFactory;
import ghidra.util.datastruct.WeakSet;
import ghidra.util.exception.AssertException;
import ghidra.util.task.BusyListener;
import utility.function.Callback;
/**
* This is the class through which operations travel that manipulate the view and graph <b>while

View file

@ -23,7 +23,6 @@ import java.util.function.Supplier;
import docking.DockingWindowManager;
import generic.concurrent.GThreadPool;
import ghidra.generic.function.Callback;
import ghidra.graph.*;
import ghidra.graph.algo.ChkDominanceAlgorithm;
import ghidra.graph.algo.ChkPostDominanceAlgorithm;
@ -34,6 +33,7 @@ import ghidra.util.SystemUtilities;
import ghidra.util.datastruct.CallbackAccumulator;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.*;
import utility.function.Callback;
/**
* A class that calculates flow between vertices and then triggers that flow to be painted

View file

@ -18,10 +18,10 @@ package ghidra.graph.algo.viewer;
import java.util.HashSet;
import java.util.Set;
import ghidra.generic.function.Callback;
import ghidra.util.Msg;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitorAdapter;
import utility.function.Callback;
/**
* Task monitor that will trigger a {@link #wait()} when {@link #checkCanceled()} is called. This

View file

@ -16,9 +16,7 @@
package ghidra.util;
import java.lang.reflect.InvocationTargetException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Supplier;
@ -159,51 +157,39 @@ public class Swing {
throws UnableToSwingException {
if (isInHeadlessMode() || SystemUtilities.isEventDispatchThread()) {
doRunSwing(r, true, SWING_RUN_ERROR_MSG);
doRun(r, true, SWING_RUN_ERROR_MSG);
return;
}
CountDownLatch start = new CountDownLatch(1);
CountDownLatch end = new CountDownLatch(1);
AtomicBoolean timedOut = new AtomicBoolean();
/*
We use the CyclicBarrier to force this thread and the Swing thread to wait for each
other. This allows the calling thread to know if/when the Swing thread starts and
the Swing thread to know if the calling thread timed-out.
*/
CyclicBarrier start = new CyclicBarrier(2);
CyclicBarrier end = new CyclicBarrier(2);
doRunSwing(() -> {
runLater(() -> {
start.countDown();
if (!waitFor(start)) {
return; // must have timed-out
}
try {
if (timedOut.get()) {
// timed-out waiting for Swing lock, but eventually did get the lock; too late now
return;
}
r.run();
}
finally {
end.countDown();
waitFor(end);
}
}, false, SWING_RUN_ERROR_MSG);
});
try {
timedOut.set(!start.await(timeout, unit));
}
catch (InterruptedException e) {
// handled below
}
if (timedOut.get()) {
if (!waitFor(start, timeout, unit)) {
throw new UnableToSwingException(
"Timed-out waiting for Swing thread lock in " + timeout + " " + unit);
}
// we've started; wait for the runnable with no timeout
try {
end.await();
}
catch (InterruptedException e) {
// we sometimes interrupt our tasks intentionally, so don't report it
}
waitFor(end);
}
/**
@ -213,7 +199,7 @@ public class Swing {
* @param r the runnable
*/
public static void runLater(Runnable r) {
doRunSwing(r, false, SWING_RUN_ERROR_MSG);
doRun(r, false, SWING_RUN_ERROR_MSG);
}
public static void runIfSwingOrRunLater(Runnable r) {
@ -230,33 +216,60 @@ public class Swing {
}
}
private static boolean waitFor(CyclicBarrier barrier, long timeout, TimeUnit unit) {
try {
barrier.await(timeout, unit);
return true;
}
catch (InterruptedException | BrokenBarrierException | TimeoutException e) {
// our Swing tasks may be interrupted from the framework
}
// timed-out or was interrupted
return false;
}
private static boolean waitFor(CyclicBarrier barrier) {
try {
barrier.await();
return true;
}
catch (InterruptedException | BrokenBarrierException e) {
// our Swing tasks may be interrupted from the framework
}
return false;
}
private static boolean isInHeadlessMode() {
return SystemUtilities.isInHeadlessMode();
}
private static void doRunSwing(Runnable r, boolean wait, String errorMessage) {
private static void doRun(Runnable r, boolean wait, String errorMessage) {
if (isInHeadlessMode()) {
r.run();
return;
}
if (wait) {
if (SwingUtilities.isEventDispatchThread()) {
r.run();
return;
}
try {
SwingUtilities.invokeAndWait(r);
}
catch (InterruptedException e) {
// we sometimes interrupt our tasks intentionally, so don't report it
}
catch (InvocationTargetException e) {
Msg.error(Swing.class, errorMessage + "\nException Message: " + e.getMessage(), e);
}
}
else {
if (!wait) {
SwingUtilities.invokeLater(r);
return;
}
if (SwingUtilities.isEventDispatchThread()) {
r.run();
return;
}
try {
SwingUtilities.invokeAndWait(r);
}
catch (InterruptedException e) {
// we sometimes interrupt our tasks intentionally, so don't report it
}
catch (InvocationTargetException e) {
Msg.error(Swing.class, errorMessage + "\nException Message: " + e.getMessage(), e);
}
}

View file

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.generic.function;
package utility.function;
/**
* A generic functional interface that is more semantically sound than {@link Runnable}. Use

View file

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.generic.function;
package utility.function;
/**
* A generic functional interface that is more semantically sound than {@link Runnable}. Use

View file

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.generic.function;
package utility.function;
/**
* A generic functional interface that allows you to consume an item and potentially throw

View file

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.generic.function;
package utility.function;
/**
* A generic functional interface that allows you to consume an item, return a result,