mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-06 03:50:02 +02:00
Merge branch 'dragonmacher-task-launcher-backgrounding-update'
This commit is contained in:
commit
8cdfe79def
28 changed files with 605 additions and 318 deletions
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue