GT-2861 - Task Monitor - removed recently added Task Monitor Service due

to conceptual issues; fixed bug in TaskLauncher that caused deadlock;
updated ImporterUtilities usage of TaskLauncher to trigger task dialog
This commit is contained in:
dragonmacher 2019-05-14 08:54:17 -04:00
parent 2108a5ed4c
commit a94c6efe68
21 changed files with 413 additions and 1452 deletions

View file

@ -42,40 +42,6 @@ public interface TaskMonitor {
*/
public boolean isCancelled();
/**
* Returns true if the monitor has been initialized
*
* @return true if the monitor has been initialized
*/
public default boolean isInitialized() {
return false;
}
/**
* Sets the initialization state of the monitor
*
* @param init true for initialized, false otherwise
*/
public default void setInitialized(boolean init) {
// do nothing - this is defaulted for backward compatibility so current
// task monitor implementations do not have to change
}
/**
* Restores the monitor to an uninitialized state. This will result in the primary
* monitor being returned from the {@link TaskMonitorService} on the next
* invocation.
*/
public default void finished() {
synchronized (this) {
setMessage("");
setProgress(0);
setMaximum(0);
setInitialized(false);
clearCanceled();
}
}
/**
* True (the default) signals to paint the progress information inside of the progress bar
*
@ -89,16 +55,6 @@ public interface TaskMonitor {
* @param message the message to display
*/
public void setMessage(String message);
/**
* Returns a version of this monitor that cannot have its progress state changed. This is
* meant for sub-tasks that should not be allowed to hijack task progress.
*
* @return null
*/
public default TaskMonitor getSecondaryMonitor() {
return null;
}
/**
* Sets the current progress value

View file

@ -1,154 +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;
import java.util.concurrent.atomic.AtomicInteger;
import javax.swing.SwingUtilities;
/**
* Provides access to the {@link TaskMonitor} instance for the current thread. The first
* time a monitor is requested via {@link #getMonitor()}, a "primary" monitor (one
* that allows updating of task progress and status messages) is returned; all
* subsequent requests will return a "secondary" monitor, which only allows
* status message updates. This is to keep the progress bar from being updated
* simultaneously by multiple parties.
* <p>
* Note: {@link TaskMonitor monitor} instances are registered with this service via the
* {@link #register(TaskMonitor) setMonitor} call, and will be available to that thread until
* the {@link #remove(int) remove} method is called.
* <p>
* Note: Because monitor instances are managed by a {@link ThreadLocal} object, they will be
* cleaned up automatically by the GC when the thread is terminated.
*/
public class TaskMonitorService {
/**
* The {@link TaskMonitor} instance. ThreadLocal ensures that each thread has access
* to its own monitor.
*/
private static ThreadLocal<TaskMonitor> localMonitor = new ThreadLocal<TaskMonitor>() {
/**
* Force the initial value to be null so users will have to call
* {@link TaskMonitorService#register(TaskMonitor) register} to assign one
*
* @return null
*/
@Override
protected TaskMonitor initialValue() {
return null;
}
};
/**
* Unique id for each thread monitor that is assigned when a monitor is
* {@link #register(TaskMonitor) registered}. This is to ensure that only clients who have
* a valid id can remove a monitor.
*/
private static ThreadLocal<Integer> localMonitorId = new ThreadLocal<Integer>() {
@Override
protected Integer initialValue() {
return nextId.getAndIncrement();
}
};
/**
* Contains the next unique id for the monitor; this is updated each time a new monitor
* is registered with the service.
*/
private static final AtomicInteger nextId = new AtomicInteger(0);
/**
* Returns the task monitor for the current thread. If one has not yet been registered,
* a {@link StubTaskMonitor stub monitor} is returned.
*
* @return the task monitor
*/
public synchronized static TaskMonitor getMonitor() {
if (localMonitor.get() == null) {
// If no monitor is available, just return a stub. The alternative is to throw an
// exception but this isn't considered an error condition in all cases.
localMonitor.set(new StubTaskMonitor());
}
// If the monitor has already been initialized, return the secondary monitor to prevent
// the caller from hijacking the progress bar
if (localMonitor.get().isInitialized()) {
return localMonitor.get().getSecondaryMonitor();
}
// This ensures that the next time this method is called, the service
// will return the secondary monitor
localMonitor.get().setInitialized(true);
return localMonitor.get();
}
/**
* Sets the given monitor for this thread
*
* @param monitor the task monitor to register
* @return the unique id for the monitor
*/
public static int register(TaskMonitor monitor) {
// Don't allow callers to register a monitor if on the swing thread
if (SwingUtilities.isEventDispatchThread()) {
throw new IllegalArgumentException("Attempting to set a monitor in the Swing thread!");
}
// Don't allow users to register a monitor if there is already one registered for this
// thread
if (localMonitor.get() != null) {
throw new IllegalArgumentException("Task monitor already assigned to this thread");
}
localMonitor.set(monitor);
return localMonitorId.get();
}
/**
* Removes the monitor from the thread local object. To protect against clients cavalierly
* removing monitors, a valid monitor id must be provided; this is generated at the time
* of monitor {@link #register(TaskMonitor) registration}.
* <p>
* Note: This should generally not need to be called as the GC will clean up thread local
* objects when the associated thread is finished.
*
* @param monitorId the unique ID for the monitor to be removed
*/
public static void remove(int monitorId) {
if (monitorId != localMonitorId.get()) {
throw new IllegalArgumentException("Invalid monitor id for this thread: " + monitorId);
}
localMonitor.remove();
}
/**
* Hide the constructor - this should not be instantiated
*/
private TaskMonitorService() {
// nothing to do
}
}