diff --git a/src/main/java/bdv/viewer/render/AccumulateProjector.java b/src/main/java/bdv/viewer/render/AccumulateProjector.java
index 980125cae767e75fc1926aa6bf60bfa83a0db365..c184991cc236c8dd4cac58a34946f1bf92ff012f 100644
--- a/src/main/java/bdv/viewer/render/AccumulateProjector.java
+++ b/src/main/java/bdv/viewer/render/AccumulateProjector.java
@@ -1,9 +1,9 @@
package bdv.viewer.render;
import java.util.ArrayList;
+import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
-import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import net.imglib2.Cursor;
@@ -43,6 +43,8 @@ public abstract class AccumulateProjector< A, B > implements VolatileProjector
*/
protected final int numThreads;
+ protected final ExecutorService executorService;
+
/**
* Time needed for rendering the last frame, in nano-seconds.
*/
@@ -57,7 +59,8 @@ public abstract class AccumulateProjector< A, B > implements VolatileProjector
final ArrayList< ? extends RandomAccessible< A > > sources,
final Converter< ? super A, B > converter,
final RandomAccessibleInterval< B > target,
- final int numThreads )
+ final int numThreads,
+ final ExecutorService executorService )
{
this.sourceProjectors = sourceProjectors;
this.sources = new ArrayList< IterableInterval< A > >();
@@ -67,6 +70,7 @@ public abstract class AccumulateProjector< A, B > implements VolatileProjector
this.target = target;
this.iterableTarget = Views.flatIterable( target );
this.numThreads = numThreads;
+ this.executorService = executorService;
lastFrameRenderNanoTime = -1;
}
@@ -96,23 +100,25 @@ public abstract class AccumulateProjector< A, B > implements VolatileProjector
final int height = ( int ) target.dimension( 1 );
final int length = width * height;
- final ExecutorService ex = Executors.newFixedThreadPool( numThreads );
- final int numTasks = Math.max( numThreads * 10, height );
+ final boolean createExecutor = ( executorService == null );
+ final ExecutorService ex = createExecutor ? Executors.newFixedThreadPool( numThreads ) : executorService;
+ final int numTasks = Math.min( numThreads * 10, height );
final double taskLength = ( double ) length / numTasks;
final int numSources = sources.size();
+ final ArrayList< Callable< Void > > tasks = new ArrayList< Callable< Void > >( numTasks );
for ( int taskNum = 0; taskNum < numTasks; ++taskNum )
{
final int myOffset = ( int ) ( taskNum * taskLength );
final int myLength = ( (taskNum == numTasks - 1 ) ? length : ( int ) ( ( taskNum + 1 ) * taskLength ) ) - myOffset;
- final Runnable r = new Runnable()
+ final Callable< Void > r = new Callable< Void >()
{
@SuppressWarnings( "unchecked" )
@Override
- public void run()
+ public Void call()
{
if ( interrupted.get() )
- return;
+ return null;
final Cursor< A >[] sourceCursors = new Cursor[ numSources ];
for ( int s = 0; s < numSources; ++s )
@@ -130,19 +136,21 @@ public abstract class AccumulateProjector< A, B > implements VolatileProjector
sourceCursors[ s ].fwd();
accumulate( sourceCursors, targetCursor.next() );
}
+ return null;
}
};
- ex.execute( r );
+ tasks.add( r );
}
- ex.shutdown();
try
{
- ex.awaitTermination( 1, TimeUnit.HOURS );
+ ex.invokeAll( tasks );
}
catch ( final InterruptedException e )
{
e.printStackTrace();
}
+ if ( createExecutor )
+ ex.shutdown();
lastFrameRenderNanoTime = stopWatch.nanoTime();
diff --git a/src/main/java/bdv/viewer/render/AccumulateProjectorARGB.java b/src/main/java/bdv/viewer/render/AccumulateProjectorARGB.java
index 481a9c4189619def08de1b2ab290a385a15db7a2..4f54315de4ae4160822f8568dad5bee1d866b0f9 100644
--- a/src/main/java/bdv/viewer/render/AccumulateProjectorARGB.java
+++ b/src/main/java/bdv/viewer/render/AccumulateProjectorARGB.java
@@ -1,6 +1,7 @@
package bdv.viewer.render;
import java.util.ArrayList;
+import java.util.concurrent.ExecutorService;
import net.imglib2.Cursor;
import net.imglib2.RandomAccessible;
@@ -14,9 +15,10 @@ public class AccumulateProjectorARGB extends AccumulateProjector< ARGBType, ARGB
final ArrayList< VolatileProjector > sourceProjectors,
final ArrayList< ? extends RandomAccessible< ARGBType > > sources,
final RandomAccessibleInterval< ARGBType > target,
- final int numThreads )
+ final int numThreads,
+ final ExecutorService executorService )
{
- super( sourceProjectors, sources, null, target, numThreads );
+ super( sourceProjectors, sources, null, target, numThreads, executorService );
}
@Override
diff --git a/src/main/java/bdv/viewer/render/MultiResolutionRenderer.java b/src/main/java/bdv/viewer/render/MultiResolutionRenderer.java
index 7b4d3541b369b4bc1a59b1469058ea73fcc0c98c..e794a060b02b0cb7f7099aa9843ec723806f6c24 100644
--- a/src/main/java/bdv/viewer/render/MultiResolutionRenderer.java
+++ b/src/main/java/bdv/viewer/render/MultiResolutionRenderer.java
@@ -571,7 +571,7 @@ public class MultiResolutionRenderer
sourceProjectors.add( p );
sourceImages.add( renderImage );
}
- projector = new AccumulateProjectorARGB( sourceProjectors, sourceImages, screenImage, numRenderingThreads );
+ projector = new AccumulateProjectorARGB( sourceProjectors, sourceImages, screenImage, numRenderingThreads, renderingExecutorService );
}
previousTimepoint = viewerState.getCurrentTimepoint();
cache.initIoTimeBudget( iobudget );