diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/threaded/IncrementalLoadJob.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/threaded/IncrementalLoadJob.java index 6113e9676b..b11de86a0c 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/threaded/IncrementalLoadJob.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/threaded/IncrementalLoadJob.java @@ -35,10 +35,9 @@ public class IncrementalLoadJob extends Job implements ThreadedTable /** * Used to signal that the updateManager has finished loading the final contents gathered - * by this job. By default, the value is 0, which means there is nothing to wait for. If we - * flush, this will be set to 1. + * by this job. This is also updated if this job is cancelled. */ - private volatile CountDownLatch completedCallbackLatch = new CountDownLatch(0); + private volatile CountDownLatch completedCallbackLatch = new CountDownLatch(1); private volatile boolean isCancelled = false; private volatile IncrementalUpdatingAccumulator incrementalAccumulator; @@ -140,14 +139,19 @@ public class IncrementalLoadJob extends Job implements ThreadedTable // -We release the lock // -A block on jobDone() can now complete as we release the lock // -jobDone() will notify listeners in an invokeLater(), which puts it behind ours - // - completedCallbackLatch = new CountDownLatch(1); + // Swing.runLater(() -> updateManager.addThreadedTableListener(IncrementalLoadJob.this)); } waitForThreadedTableUpdateManagerToFinish(); } + /** + * Waits for the final flushed data to be added to the table. We will get called when the data + * is finished loading or cancelled. The latch will also be released if the cancel method of + * this job is called. This can happen if the work queue is told to cancel all jobs, which can + * happen if a new reload job is requested. + */ private void waitForThreadedTableUpdateManagerToFinish() { try { completedCallbackLatch.await(); @@ -179,6 +183,7 @@ public class IncrementalLoadJob extends Job implements ThreadedTable super.cancel(); isCancelled = true; incrementalAccumulator.cancel(); + completedCallbackLatch.countDown(); // Note: cannot do this here, since the cancel() call may happen asynchronously and after // a call to reload() on the table model. Assume that the model itself has already diff --git a/Ghidra/Framework/Generic/src/main/java/generic/concurrent/ConcurrentQ.java b/Ghidra/Framework/Generic/src/main/java/generic/concurrent/ConcurrentQ.java index f7c1e45ea3..6b91d4ea4c 100644 --- a/Ghidra/Framework/Generic/src/main/java/generic/concurrent/ConcurrentQ.java +++ b/Ghidra/Framework/Generic/src/main/java/generic/concurrent/ConcurrentQ.java @@ -4,9 +4,9 @@ * 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. @@ -56,7 +56,7 @@ import ghidra.util.task.TaskMonitor; *
  * {@literal QCallback callback = new AbstractQCallback()} {
  *     public RESULT process(ITEM item, TaskMonitor monitor) {
- *         // do work here...
+ *         // do work here and create a RESULT item for later processing...
  *     }
  * };
  *
@@ -85,7 +85,7 @@ import ghidra.util.task.TaskMonitor;
  * 
{@literal
  * QCallback callback = new AbstractQCallback() {
  *     public RESULT process(ITEM item, TaskMonitor monitor) {
- *         // do work here...
+ *         // do work here and create a RESULT item for later processing...
  *     }
  * };}
  *
@@ -652,6 +652,7 @@ public class ConcurrentQ {
 		}
 	}
 
+	// Called by the FutureTaskMonitor that we gave to the thread pool
 	private class CallbackCallable implements Callable {
 
 		private I item;
@@ -663,6 +664,7 @@ public class ConcurrentQ {
 
 		@Override
 		public R call() throws Exception {
+			// callback is the client callback given to this queue at construction
 			return callback.process(item, future);
 		}