mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 10:49:34 +02:00
GT-2875 - Unswingable - review fixes
This commit is contained in:
parent
8dffd377fb
commit
07f0371a50
16 changed files with 395 additions and 374 deletions
|
@ -15,8 +15,7 @@
|
|||
*/
|
||||
package docking.test;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.datatransfer.*;
|
||||
|
@ -1760,9 +1759,11 @@ public abstract class AbstractDockingTest extends AbstractGenericTest {
|
|||
*/
|
||||
public static void setErrorsExpected(boolean expected) {
|
||||
if (expected) {
|
||||
Msg.error(AbstractDockingTest.class, ">>>>>>>>>>>>>>>> Expected Exception");
|
||||
ConcurrentTestExceptionHandler.disable();
|
||||
}
|
||||
else {
|
||||
Msg.error(AbstractDockingTest.class, "<<<<<<<<<<<<<<<< End Expected Exception");
|
||||
ConcurrentTestExceptionHandler.enable();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -221,7 +221,8 @@ public abstract class DataLoadingConstraintEditor<T> extends AbstractColumnConst
|
|||
reloadDataButton.setVisible(false);
|
||||
Task task = new LoadDataTask();
|
||||
task.addTaskListener(this);
|
||||
new TaskLauncher(task, (TaskMonitor) taskMonitorComponent);
|
||||
BackgroundThreadTaskLauncher launcher = new BackgroundThreadTaskLauncher(task);
|
||||
launcher.run(taskMonitorComponent);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -15,29 +15,39 @@
|
|||
*/
|
||||
package ghidra.util.task;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import generic.concurrent.GThreadPool;
|
||||
import ghidra.util.Swing;
|
||||
import ghidra.util.TaskUtilities;
|
||||
|
||||
/**
|
||||
* Helper class to launch the given task in a background thread This helper will not
|
||||
* show a task dialog. See {@link TaskLauncher}.
|
||||
* show a task dialog.
|
||||
*
|
||||
* <p>This class is useful when you want to run the task and use a monitor that is embedded
|
||||
* in some other component.
|
||||
*
|
||||
* <p>See {@link TaskLauncher}.
|
||||
*/
|
||||
class BackgroundThreadTaskLauncher {
|
||||
public class BackgroundThreadTaskLauncher {
|
||||
|
||||
private Task task;
|
||||
|
||||
BackgroundThreadTaskLauncher(Task task) {
|
||||
public BackgroundThreadTaskLauncher(Task task) {
|
||||
this.task = task;
|
||||
}
|
||||
|
||||
void run(TaskMonitor monitor) {
|
||||
public void run(TaskMonitor monitor) {
|
||||
// add the task here, so we can track it before it is actually started by the thread
|
||||
TaskUtilities.addTrackedTask(task, monitor);
|
||||
|
||||
String name = "Task - " + task.getTaskTitle();
|
||||
Thread taskThread = new Thread(() -> {
|
||||
GThreadPool pool = GThreadPool.getSharedThreadPool(Swing.GSWING_THREAD_POOL_NAME);
|
||||
Executor executor = pool.getExecutor();
|
||||
executor.execute(() -> {
|
||||
Thread.currentThread().setName(name);
|
||||
task.monitoredRun(monitor);
|
||||
}, name);
|
||||
taskThread.setPriority(Thread.MIN_PRIORITY);
|
||||
taskThread.start();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,32 +0,0 @@
|
|||
/* ###
|
||||
* 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.util.task;
|
||||
|
||||
/**
|
||||
* Helper class to launch the given task in the current thread. See {@link TaskLauncher}.
|
||||
*/
|
||||
class CurrentThreadTaskLauncher {
|
||||
|
||||
private Task task;
|
||||
|
||||
CurrentThreadTaskLauncher(Task task) {
|
||||
this.task = task;
|
||||
}
|
||||
|
||||
void run() {
|
||||
task.monitoredRun(TaskMonitor.DUMMY);
|
||||
}
|
||||
}
|
|
@ -18,9 +18,7 @@ package ghidra.util.task;
|
|||
import java.awt.Component;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.swing.SwingUtilities;
|
||||
|
||||
import ghidra.util.SystemUtilities;
|
||||
import ghidra.util.Swing;
|
||||
import ghidra.util.exception.UnableToSwingException;
|
||||
|
||||
/**
|
||||
|
@ -232,34 +230,19 @@ public class TaskLauncher {
|
|||
public TaskLauncher(Task task, Component parent, int delay, int dialogWidth) {
|
||||
|
||||
try {
|
||||
runSwing(task, parent, delay, dialogWidth);
|
||||
scheduleFromSwingThread(task, parent, delay, dialogWidth);
|
||||
}
|
||||
catch (UnableToSwingException e) {
|
||||
runInThisBackgroundThread(task);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor where an external taskMonitor is used. Normally, this class will provide
|
||||
* the {@link TaskDialog} as the monitor. This constructor is useful when you want to run
|
||||
* the task and use a monitor that is embedded in some other component.
|
||||
*
|
||||
* <p>See <a href="#modal_usage">notes on modal usage</a>
|
||||
*
|
||||
* @param task task to run in another thread (other than the Swing Thread)
|
||||
* @param monitor the monitor to use while running the task.
|
||||
*/
|
||||
public TaskLauncher(Task task, TaskMonitor monitor) {
|
||||
BackgroundThreadTaskLauncher runner = new BackgroundThreadTaskLauncher(task);
|
||||
runner.run(monitor);
|
||||
}
|
||||
|
||||
private void runSwing(Task task, Component parent, int delay, int dialogWidth)
|
||||
private void scheduleFromSwingThread(Task task, Component parent, int delay, int dialogWidth)
|
||||
throws UnableToSwingException {
|
||||
|
||||
SwingTaskLauncher swinger = buildSwingLauncher(task, parent, delay, dialogWidth);
|
||||
if (SwingUtilities.isEventDispatchThread()) {
|
||||
swinger.run();
|
||||
TaskRunner runner = createTaskRunner(task, parent, delay, dialogWidth);
|
||||
if (Swing.isEventDispatchThread()) {
|
||||
runner.run();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -271,26 +254,28 @@ public class TaskLauncher {
|
|||
// This will throw an exception if we could not get the Swing lock. When that happens,
|
||||
// the task was NOT run.
|
||||
int timeout = getSwingTimeoutInSeconds();
|
||||
SystemUtilities.runSwingNow(() -> {
|
||||
swinger.run();
|
||||
}, timeout, TimeUnit.SECONDS);
|
||||
Swing.runNow(() -> runner.run(), timeout, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
protected int getSwingTimeoutInSeconds() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
protected SwingTaskLauncher buildSwingLauncher(Task task, Component parent, int delay,
|
||||
int dialogWidth) {
|
||||
return new SwingTaskLauncher(task, parent, delay, dialogWidth);
|
||||
protected TaskRunner createTaskRunner(Task task, Component parent, int delay, int dialogWidth) {
|
||||
return new TaskRunner(task, parent, delay, dialogWidth);
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the given task in the current thread, which <b>cannot be the Swing thread</b>
|
||||
*
|
||||
* @param task the task to run
|
||||
* @throws IllegalStateException if the given thread is the Swing thread
|
||||
*/
|
||||
protected void runInThisBackgroundThread(Task task) {
|
||||
if (SwingUtilities.isEventDispatchThread()) {
|
||||
if (Swing.isEventDispatchThread()) {
|
||||
throw new IllegalStateException("Must not call this method from the Swing thread");
|
||||
}
|
||||
|
||||
CurrentThreadTaskLauncher runner = new CurrentThreadTaskLauncher(task);
|
||||
runner.run();
|
||||
task.monitoredRun(TaskMonitor.DUMMY);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,17 +16,18 @@
|
|||
package ghidra.util.task;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import javax.swing.SwingUtilities;
|
||||
|
||||
import generic.concurrent.GThreadPool;
|
||||
import generic.util.WindowUtilities;
|
||||
import ghidra.util.*;
|
||||
import ghidra.util.Swing;
|
||||
import ghidra.util.TaskUtilities;
|
||||
|
||||
/**
|
||||
* Helper class to launch the given task in a background thread, showing a task dialog if
|
||||
* this task takes to long. See {@link TaskLauncher}.
|
||||
*/
|
||||
class SwingTaskLauncher {
|
||||
class TaskRunner {
|
||||
|
||||
protected Task task;
|
||||
private Component parent;
|
||||
|
@ -43,7 +44,7 @@ class SwingTaskLauncher {
|
|||
}
|
||||
};
|
||||
|
||||
SwingTaskLauncher(Task task, Component parent, int delay, int dialogWidth) {
|
||||
TaskRunner(Task task, Component parent, int delay, int dialogWidth) {
|
||||
this.task = task;
|
||||
this.parent = parent;
|
||||
this.delay = delay;
|
||||
|
@ -51,26 +52,16 @@ class SwingTaskLauncher {
|
|||
}
|
||||
|
||||
void run() {
|
||||
|
||||
// note: we need to be on the Swing thread to create our UI widgets
|
||||
Swing.assertThisIsTheSwingThread(
|
||||
"The Task runner is required to be run from the Swing thread");
|
||||
|
||||
this.taskDialog = buildTaskDialog(parent);
|
||||
|
||||
startBackgroundThread(taskDialog);
|
||||
|
||||
taskDialog.show(Math.max(delay, 0));
|
||||
|
||||
waitIfNotSwing();
|
||||
}
|
||||
|
||||
private void waitIfNotSwing() {
|
||||
if (SwingUtilities.isEventDispatchThread() || !task.isModal()) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
taskThread.join();
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
Msg.debug(this, "Task Launcher unexpectedly interrupted waiting for task thread", e);
|
||||
}
|
||||
}
|
||||
|
||||
protected TaskDialog buildTaskDialog(Component comp) {
|
||||
|
@ -80,10 +71,8 @@ class SwingTaskLauncher {
|
|||
// on the Swing thread to prevent exceptions while painting (as seen when using the
|
||||
// Nimbus Look and Feel).
|
||||
//
|
||||
SystemUtilities.runSwingNow(() -> {
|
||||
taskDialog = createTaskDialog(comp);
|
||||
taskDialog.setMinimumSize(dialogWidth, 0);
|
||||
});
|
||||
taskDialog = createTaskDialog(comp);
|
||||
taskDialog.setMinimumSize(dialogWidth, 0);
|
||||
|
||||
if (task.isInterruptible() || task.isForgettable()) {
|
||||
taskDialog.addCancelledListener(monitorChangeListener);
|
||||
|
@ -100,21 +89,16 @@ class SwingTaskLauncher {
|
|||
TaskUtilities.addTrackedTask(task, monitor);
|
||||
|
||||
String name = "Task - " + task.getTaskTitle();
|
||||
taskThread = new Thread(() -> {
|
||||
GThreadPool pool = GThreadPool.getSharedThreadPool(Swing.GSWING_THREAD_POOL_NAME);
|
||||
Executor executor = pool.getExecutor();
|
||||
executor.execute(() -> {
|
||||
Thread.currentThread().setName(name);
|
||||
task.monitoredRun(monitor);
|
||||
taskProcessed();
|
||||
}, name);
|
||||
taskThread.setPriority(Thread.MIN_PRIORITY);
|
||||
taskThread.start();
|
||||
}
|
||||
|
||||
private void taskProcessed() {
|
||||
if (taskDialog != null) {
|
||||
taskDialog.taskProcessed();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected TaskDialog createTaskDialog(Component comp) {
|
||||
private TaskDialog createTaskDialog(Component comp) {
|
||||
Component currentParent = comp;
|
||||
if (currentParent != null) {
|
||||
currentParent = WindowUtilities.windowForComponent(comp);
|
Loading…
Add table
Add a link
Reference in a new issue