mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 10:19:23 +02:00
GT-2875 - Unswingable - review fixes
This commit is contained in:
parent
5e8340b7f8
commit
31f3cca1a5
27 changed files with 100 additions and 79 deletions
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
/* ###
|
||||
* 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 utility.function;
|
||||
|
||||
/**
|
||||
* A generic functional interface that is more semantically sound than {@link Runnable}. Use
|
||||
* anywhere you wish to have a generic callback function.
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface Callback {
|
||||
|
||||
/**
|
||||
* Creates a dummy callback function. This is useful to avoid using <tt>null</tt>.
|
||||
* @return a dummy callback function
|
||||
*/
|
||||
public static Callback dummy() {
|
||||
return () -> {
|
||||
// no-op
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the given callback object if it is not <tt>null</tt>. Otherwise, a {@link #dummy()}
|
||||
* callback is returned. This is useful to avoid using <tt>null</tt>.
|
||||
*
|
||||
* @param c the callback function to check for <tt>null</tt>
|
||||
* @return a non-null callback function
|
||||
*/
|
||||
public static Callback dummyIfNull(Callback c) {
|
||||
if (c == null) {
|
||||
return dummy();
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* The method that will be called.
|
||||
*/
|
||||
public void call();
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/* ###
|
||||
* 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 utility.function;
|
||||
|
||||
/**
|
||||
* A generic functional interface that is more semantically sound than {@link Runnable}. Use
|
||||
* anywhere you wish to have a generic callback function and you need to throw an exception.
|
||||
*
|
||||
* @param <E> the exception of your choice
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface ExceptionalCallback<E extends Exception> {
|
||||
|
||||
/**
|
||||
* The method that will be called
|
||||
*
|
||||
* @throws Exception if the call throws an exception
|
||||
*/
|
||||
public void call() throws E;
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
/* ###
|
||||
* 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 utility.function;
|
||||
|
||||
/**
|
||||
* A generic functional interface that allows you to consume an item and potentially throw
|
||||
* an exception.
|
||||
*
|
||||
* @param <T> the input type
|
||||
* @param <E> the exception of your choice
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface ExceptionalConsumer<T, E extends Exception> {
|
||||
|
||||
/**
|
||||
* The method that will be called
|
||||
*
|
||||
* @param t the input
|
||||
* @throws E if the call throws an exception
|
||||
*/
|
||||
public void accept(T t) throws E;
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/* ###
|
||||
* 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 utility.function;
|
||||
|
||||
/**
|
||||
* A generic functional interface that allows you to consume an item, return a result,
|
||||
* and potentially throw an exception.
|
||||
*
|
||||
* @param <I> the input type
|
||||
* @param <R> the result type
|
||||
* @param <E> the exception of your choice
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface ExceptionalFunction<I, R, E extends Exception> {
|
||||
|
||||
/**
|
||||
* The method that will be called
|
||||
*
|
||||
* @param i the input
|
||||
* @return the result of the call
|
||||
* @throws E if the call throws an exception
|
||||
*/
|
||||
public R apply(I i) throws E;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue