From 3738e8be3a070c4cd4321cef0ae492b86afcde1b Mon Sep 17 00:00:00 2001
From: Tobias Pietzsch <tobias.pietzsch@gmail.com>
Date: Wed, 5 Mar 2014 11:59:01 -0500
Subject: [PATCH] pass re-usable ExecutorService to AccumulateProjector, and
 fix min/max bug in calcuation of numTasks.

---
 .../viewer/render/AccumulateProjector.java    | 28 ++++++++++++-------
 .../render/AccumulateProjectorARGB.java       |  6 ++--
 .../render/MultiResolutionRenderer.java       |  2 +-
 3 files changed, 23 insertions(+), 13 deletions(-)

diff --git a/src/main/java/bdv/viewer/render/AccumulateProjector.java b/src/main/java/bdv/viewer/render/AccumulateProjector.java
index 980125ca..c184991c 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 481a9c41..4f54315d 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 7b4d3541..e794a060 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 );
-- 
GitLab