Merge branch 'dragonmacher-task-launcher-backgrounding-update'

This commit is contained in:
dragonmacher 2019-05-23 18:26:53 -04:00
commit 8cdfe79def
28 changed files with 605 additions and 318 deletions

View file

@ -40,15 +40,20 @@ import ghidra.util.task.TaskMonitor;
* On ConcurrentQs that only allow one task to run at a time, when a task is cancelled,
* the next task can begin. Most likely, the thread that was running the cancelled
* task won't be free, and a new thread will be used to start running the next task.
*
* @param <I> the input type
* @param <R> the output type
*/
class FutureTaskMonitor<I, R> extends FutureTask<R> implements TaskMonitor {
private final ConcurrentQ<I, R> queue;
private final I item;
private final long id;
private volatile String lastMessage;
private volatile long currentProgress;
private volatile long maxProgress;
private volatile CancelledListener cancelledListener;
private volatile boolean isIndeterminate;
FutureTaskMonitor(ConcurrentQ<I, R> queue, Callable<R> callable, I item, long id) {
super(callable);
@ -103,6 +108,11 @@ class FutureTaskMonitor<I, R> extends FutureTask<R> implements TaskMonitor {
queue.progressMessageChanged(id, item, message);
}
@Override
public String getMessage() {
return lastMessage;
}
@Override
public void initialize(long max) {
currentProgress = 0;
@ -123,9 +133,15 @@ class FutureTaskMonitor<I, R> extends FutureTask<R> implements TaskMonitor {
@Override
public void setIndeterminate(boolean indeterminate) {
this.isIndeterminate = indeterminate;
queue.progressModeChanged(id, item, indeterminate);
}
@Override
public boolean isIndeterminate() {
return isIndeterminate;
}
@Override
public long getProgress() {
return currentProgress;

View file

@ -220,28 +220,6 @@ public abstract class Task implements MonitoredRunnable {
return isModal;
}
public boolean isInterruptible() {
return isInterruptible;
}
public void setInterruptible(boolean interruptible) {
this.isInterruptible = interruptible;
}
/**
* Returns true if this task should be left alone to die when cancelled, as opposed to being
* interrupted
*
* @return true if forgettable
*/
public boolean isForgettable() {
return isForgettable;
}
public void setForgettable(boolean isForgettable) {
this.isForgettable = isForgettable;
}
/**
* Sets the task listener on this task. It is a programming error to call this method more
* than once or to call this method if a listener was passed into the constructor of this class.

View file

@ -67,6 +67,11 @@ public class TaskMonitorAdapter implements TaskMonitor {
// do nothing
}
@Override
public String getMessage() {
return null;
}
@Override
public void setProgress(long value) {
// do nothing
@ -105,6 +110,11 @@ public class TaskMonitorAdapter implements TaskMonitor {
// do nothing
}
@Override
public boolean isIndeterminate() {
return false;
}
@Override
public synchronized void setCancelEnabled(boolean enable) {
cancelEnabled = enable;
@ -134,6 +144,8 @@ public class TaskMonitorAdapter implements TaskMonitor {
}
cancelled = false;
}
// TODO this seems like a mistake, to notify of 'cancelled' when clearning
notifyChangeListeners();
}

View file

@ -136,6 +136,11 @@ public class TaskMonitorSplitter {
parent.setIndeterminate(indeterminate);
}
@Override
public boolean isIndeterminate() {
return parent.isIndeterminate();
}
@Override
public void initialize(long newMax) {
setMaximum(newMax);
@ -152,7 +157,11 @@ public class TaskMonitorSplitter {
@Override
public void setMessage(String message) {
parent.setMessage(message);
}
@Override
public String getMessage() {
return parent.getMessage();
}
@Override

View file

@ -139,6 +139,11 @@ public class TimeoutTaskMonitor implements TaskMonitor {
delegate.setMessage(message);
}
@Override
public String getMessage() {
return delegate.getMessage();
}
@Override
public void setProgress(long value) {
delegate.setProgress(value);
@ -164,6 +169,11 @@ public class TimeoutTaskMonitor implements TaskMonitor {
delegate.setIndeterminate(indeterminate);
}
@Override
public boolean isIndeterminate() {
return delegate.isIndeterminate();
}
@Override
public void checkCanceled() throws CancelledException {
if (didTimeout()) {

View file

@ -15,16 +15,30 @@
*/
package ghidra.util.task;
import ghidra.util.datastruct.WeakDataStructureFactory;
import ghidra.util.datastruct.WeakSet;
import ghidra.util.exception.CancelledException;
/**
* An implementation of the {@link TaskMonitor} interface that simply wraps a delegate task
* monitor. This is useful for classes that wish to wrap a task monitor, changing behavior
* as needed by overriding a subset of methods.
*
* <p><b>Synchronization Policy</b>:<br>
* We wish for this class to be performant. Thus, we do not synchronize the methods of this
* class. The {@link #setDelegate(TaskMonitor)} is synchronized to ensure thread visibility
* for the state of the delegate monitor.
*
* <p>When calling {@link #setDelegate(TaskMonitor)} there is the potential for the values being
* transferred to become inconsistent with any new values being set. We have decided that this
* does not much matter for the overall progress or the messages on the monitor. However, most
* of the other setter methods could lead to bad behavior if they are inconsistent.
*/
public class WrappingTaskMonitor implements TaskMonitor {
protected final TaskMonitor delegate;
private WeakSet<CancelledListener> listeners =
WeakDataStructureFactory.createCopyOnReadWeakSet();
protected TaskMonitor delegate;
/**
* Constructor
@ -35,8 +49,36 @@ public class WrappingTaskMonitor implements TaskMonitor {
this.delegate = delegate;
}
/**
* Sets the delegate of this wrapper to be the new value. The new delegate will be
* initialized with the current values of the existing delegate.
*
* @param newDelegate the new delegate
*/
public synchronized void setDelegate(TaskMonitor newDelegate) {
// if the existing monitor has already been cancelled, then do not apply the state
if (delegate.isCancelled()) {
newDelegate.cancel();
return;
}
for (CancelledListener l : listeners) {
newDelegate.addCancelledListener(l);
delegate.removeCancelledListener(l);
}
newDelegate.setMaximum(delegate.getMaximum());
newDelegate.setProgress(delegate.getProgress());
newDelegate.setMessage(delegate.getMessage());
newDelegate.setIndeterminate(delegate.isIndeterminate());
newDelegate.setCancelEnabled(delegate.isCancelEnabled());
this.delegate = newDelegate;
}
@Override
public boolean isCancelled() {
public synchronized boolean isCancelled() {
return delegate.isCancelled();
}
@ -50,6 +92,11 @@ public class WrappingTaskMonitor implements TaskMonitor {
delegate.setMessage(message);
}
@Override
public String getMessage() {
return delegate.getMessage();
}
@Override
public void setProgress(long value) {
delegate.setProgress(value);
@ -61,7 +108,7 @@ public class WrappingTaskMonitor implements TaskMonitor {
}
@Override
public void setMaximum(long max) {
public synchronized void setMaximum(long max) {
delegate.setMaximum(max);
}
@ -71,10 +118,15 @@ public class WrappingTaskMonitor implements TaskMonitor {
}
@Override
public void setIndeterminate(boolean indeterminate) {
public synchronized void setIndeterminate(boolean indeterminate) {
delegate.setIndeterminate(indeterminate);
}
@Override
public boolean isIndeterminate() {
return delegate.isIndeterminate();
}
@Override
public void checkCanceled() throws CancelledException {
delegate.checkCanceled();
@ -91,22 +143,24 @@ public class WrappingTaskMonitor implements TaskMonitor {
}
@Override
public void cancel() {
public synchronized void cancel() {
delegate.cancel();
}
@Override
public void addCancelledListener(CancelledListener listener) {
public synchronized void addCancelledListener(CancelledListener listener) {
listeners.add(listener);
delegate.addCancelledListener(listener);
}
@Override
public void removeCancelledListener(CancelledListener listener) {
public synchronized void removeCancelledListener(CancelledListener listener) {
listeners.remove(listener);
delegate.removeCancelledListener(listener);
}
@Override
public void setCancelEnabled(boolean enable) {
public synchronized void setCancelEnabled(boolean enable) {
delegate.setCancelEnabled(enable);
}
@ -116,7 +170,7 @@ public class WrappingTaskMonitor implements TaskMonitor {
}
@Override
public void clearCanceled() {
public synchronized void clearCanceled() {
delegate.clearCanceled();
}
}