Fixed a few cases of SwingUpdateManager not getting disposed; introduced

speed improvements to the tests' waitForSwing() call
This commit is contained in:
dragonmacher 2020-12-30 13:06:14 -05:00
parent 881282d96a
commit 6e8811d087
8 changed files with 102 additions and 38 deletions

View file

@ -1113,7 +1113,7 @@ public abstract class AbstractGenericTest extends AbstractGTest {
*
* @param r the runnable code snippet
*/
public void runSwingLater(Runnable r) {
public static void runSwingLater(Runnable r) {
runSwing(r, false);
}
@ -1603,23 +1603,34 @@ public abstract class AbstractGenericTest extends AbstractGTest {
(WeakSet<SwingUpdateManager>) getInstanceField("instances",
SwingUpdateManager.class);
for (AbstractSwingUpdateManager manager : s) {
// Ignore update managers that fire often and are unlikely to affect tests.
// (Hardcoding this is brittle, but these update managers live in lower packages
// and a larger refactoring didn't seem worth the cost at this time.)
String name = manager.getName();
if (name.equals("Context Updater") ||
name.equals("Docking Windows Updater")) {
continue;
}
set.add(manager);
}
});
/*
// performance debug
long start = System.nanoTime();
boolean wasEverBusy = waitForSwing(set, true);
boolean wasEverBusy = waitForSwing(set);
long end = System.nanoTime();
Msg.out("\twaitForSwing() - " +
TimeUnit.MILLISECONDS.convert(end - start, TimeUnit.NANOSECONDS));
*/
boolean wasEverBusy = waitForSwing(set, true);
boolean wasEverBusy = waitForSwing(set);
return wasEverBusy;
}
private static boolean waitForSwing(Set<AbstractSwingUpdateManager> managers, boolean flush) {
private static boolean waitForSwing(Set<AbstractSwingUpdateManager> managers) {
// Note: not sure how long is too long to wait for the Swing thread and update managers
// to finish. This is usually less than a second. We have seen a degenerate
@ -1629,7 +1640,7 @@ public abstract class AbstractGenericTest extends AbstractGTest {
int totalTime = 0;
// flush all managers up front to get them started before we check them
flushAllManagers(managers, flush);
flushAllManagers(managers);
boolean wasEverBusy = false;
boolean keepGoing = true;
@ -1648,14 +1659,13 @@ public abstract class AbstractGenericTest extends AbstractGTest {
// Msg.out("busy manager: " + manager.toStringDebug());
doFlush(flush, manager);
doFlush(manager);
keepGoing = true; // true, since we had a busy signal
wasEverBusy = true;
boolean isBusy = true;
while (isBusy) {
keepGoing = true; // true, since we had a busy signal
wasEverBusy = true;
totalTime += sleep(DEFAULT_WAIT_DELAY);
if (totalTime >= MAX_SWING_TIMEOUT) {
// eject!
@ -1676,7 +1686,7 @@ public abstract class AbstractGenericTest extends AbstractGTest {
return wasEverBusy;
}
private static void flushAllManagers(Set<AbstractSwingUpdateManager> managers, boolean flush) {
private static void flushAllManagers(Set<AbstractSwingUpdateManager> managers) {
//
// Some update managers will make an update that causes another manager to schedule an
@ -1693,21 +1703,26 @@ public abstract class AbstractGenericTest extends AbstractGTest {
// which would be 2
int n = 3;
for (int i = 0; i < n; i++) {
boolean didFlush = false;
for (AbstractSwingUpdateManager manager : managers) {
doFlush(flush, manager);
didFlush = doFlush(manager);
}
if (!didFlush) {
return; // skip extra waiting when no work was done
}
}
}
private static void doFlush(boolean doFlush, AbstractSwingUpdateManager manager) {
if (!doFlush) {
return;
private static boolean doFlush(AbstractSwingUpdateManager manager) {
if (!manager.hasPendingUpdates()) {
return false; // skip the yield call, as it consumes time
}
runSwing(() -> {
manager.flush();
}, false);
runSwingLater(() -> manager.flush());
yieldToSwing();
return true;
}
/**

View file

@ -56,7 +56,6 @@ public abstract class AbstractSwingUpdateManager {
public static final int DEFAULT_MAX_DELAY = 30000;
protected static final int MIN_DELAY_FLOOR = 10;
protected static final int DEFAULT_MIN_DELAY = 250;
protected static final String DEFAULT_NAME = AbstractSwingUpdateManager.class.getSimpleName();
private static final WeakSet<AbstractSwingUpdateManager> instances =
WeakDataStructureFactory.createCopyOnReadWeakSet();
@ -107,7 +106,7 @@ public abstract class AbstractSwingUpdateManager {
* @param maxDelay the maximum amount of time to wait between gui updates.
*/
protected AbstractSwingUpdateManager(int minDelay, int maxDelay) {
this(minDelay, maxDelay, DEFAULT_NAME);
this(minDelay, maxDelay, null);
}
/**
@ -124,7 +123,7 @@ public abstract class AbstractSwingUpdateManager {
protected AbstractSwingUpdateManager(int minDelay, int maxDelay, String name) {
this.maxDelay = maxDelay;
this.name = name;
this.name = name != null ? name : getClass().getSimpleName();
recordInception();
this.minDelay = Math.max(MIN_DELAY_FLOOR, minDelay);
@ -183,6 +182,15 @@ public abstract class AbstractSwingUpdateManager {
Swing.runNow(this::checkForWork);
}
/**
* Returns the name given to this update manager. If no name was provided at construction,
* then the class name is used.
* @return the name
*/
public String getName() {
return name;
}
/**
* Causes this run manager to run if it has a pending update
*/
@ -363,12 +371,10 @@ public abstract class AbstractSwingUpdateManager {
StackTraceElement[] trace = t.getStackTrace();
String classInfo = trace[0].toString();
/*
// debug source of creation
Throwable filtered = ReflectionUtilities.filterJavaThrowable(t);
String string = ReflectionUtilities.stackTraceToString(filtered);
classInfo = classInfo + "\n\tfrom:\n\n" + string;
*/
return classInfo;
}

View file

@ -36,11 +36,11 @@ public class BufferedSwingRunner extends AbstractSwingUpdateManager {
* @param maxDelay the maximum amount of time to wait between gui updates.
*/
public BufferedSwingRunner(int minDelay, int maxDelay) {
super(minDelay, maxDelay, DEFAULT_NAME);
super(minDelay, maxDelay, null);
}
public BufferedSwingRunner() {
super(DEFAULT_MIN_DELAY, DEFAULT_MAX_DELAY, DEFAULT_NAME);
super(DEFAULT_MIN_DELAY, DEFAULT_MAX_DELAY, null);
}
@Override

View file

@ -82,8 +82,7 @@ public class SwingUpdateManager extends AbstractSwingUpdateManager {
* @param r the runnable that performs the client work.
*/
public SwingUpdateManager(int minDelay, int maxDelay, Runnable r) {
super(minDelay, maxDelay, DEFAULT_NAME);
this.clientRunnable = r;
this(minDelay, maxDelay, null, r);
}
/**