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 );