gt: 			return this.state.get() == State.DONE;
context: /*
   * HA-JDBC: High-Availability JDBC
   * Copyright (C) 2012  Paul Ferraro
   *
   * This program is free software: you can redistribute it and/or modify
   * it under the terms of the GNU Lesser General Public License as published by
   * the Free Software Foundation, either version 3 of the License, or
   * (at your option) any later version.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public License
   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
   */
  package net.sf.hajdbc.util.concurrent;
  
  import java.util.ArrayList;
  import java.util.Collection;
  import java.util.Collections;
  import java.util.LinkedList;
  import java.util.List;
  import java.util.concurrent.AbstractExecutorService;
  import java.util.concurrent.Callable;
  import java.util.concurrent.CancellationException;
  import java.util.concurrent.CountDownLatch;
  import java.util.concurrent.ExecutionException;
  import java.util.concurrent.ExecutorService;
  import java.util.concurrent.Executors;
  import java.util.concurrent.Future;
  import java.util.concurrent.TimeUnit;
  import java.util.concurrent.TimeoutException;
  import java.util.concurrent.atomic.AtomicReference;
  
  import net.sf.hajdbc.util.Reversed;
  
  /**
   * Executor service that executes tasks in the caller thread.
   * 
   * @author Paul Ferraro
   */
  public class SynchronousExecutor extends AbstractExecutorService
  {
  	private final ExecutorService executor;
  	private final boolean reverse;
  	
  	public SynchronousExecutor(ExecutorService executor)
  	{
  		this(executor, false);
  	}
  	
  	public SynchronousExecutor(ExecutorService executor, boolean reverse)
  	{
  		this.executor = executor;
  		this.reverse = reverse;
  	}
  	
  	/**
  	 * @see java.util.concurrent.ExecutorService#awaitTermination(long, java.util.concurrent.TimeUnit)
  	 */
  	@Override
  	public boolean awaitTermination(long time, TimeUnit unit) throws InterruptedException
  	{
  		return this.executor.awaitTermination(time, unit);
  	}
  
  	/**
  	 * @see java.util.concurrent.ExecutorService#isShutdown()
  	 */
  	@Override
  	public boolean isShutdown()
  	{
  		return this.executor.isShutdown();
  	}
  
  	/**
  	 * @see java.util.concurrent.ExecutorService#isTerminated()
  	 */
  	@Override
  	public boolean isTerminated()
  	{
  		return this.executor.isTerminated();
  	}
  
  	/**
  	 * @see java.util.concurrent.ExecutorService#shutdown()
  	 */
  	@Override
  	public void shutdown()
  	{
  		this.executor.shutdown();
  	}
  
  	/**
  	 * @see java.util.concurrent.ExecutorService#shutdownNow()
  	 */
  	@Override
  	public List<Runnable> shutdownNow()
  	{
  		return this.executor.shutdownNow();
  	}
  
  	/**
  	 * @see java.util.concurrent.Executor#execute(java.lang.Runnable)
  	 */
  	@Override
  	public void execute(Runnable task)
  	{
  		task.run();
  	}
  
  	/**
  	 * {@inheritDoc}
  	 * @see java.util.concurrent.AbstractExecutorService#submit(java.lang.Runnable)
  	 */
  	@Override
  	public Future<?> submit(Runnable task)
  	{
  		return this.submit(Executors.callable(task));
  	}
  
  	/**
  	 * {@inheritDoc}
  	 * @see java.util.concurrent.AbstractExecutorService#submit(java.lang.Runnable, java.lang.Object)
  	 */
  	@Override
  	public <T> Future<T> submit(Runnable task, T result)
  	{
  		return this.submit(Executors.callable(task, result));
  	}
  
  	/**
  	 * {@inheritDoc}
  	 * @see java.util.concurrent.AbstractExecutorService#submit(java.util.concurrent.Callable)
  	 */
  	@Override
  	public <T> Future<T> submit(Callable<T> task)
  	{
  		return new EagerFuture<>(task);
  	}
  
  	/**
  	 * Executes the specified tasks serially, until the first successful result, then the remainder using the executor with which this executor was created.
  	 * {@inheritDoc}
  	 * @see java.util.concurrent.AbstractExecutorService#invokeAll(java.util.Collection)
  	 */
  	@Override
  	public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) throws InterruptedException
  	{
  		return this.invokeAll(tasks, Long.MAX_VALUE, TimeUnit.MILLISECONDS);
  	}
  
  	/**
  	 * {@inheritDoc}
  	 * @see java.util.concurrent.AbstractExecutorService#invokeAll(java.util.Collection, long, java.util.concurrent.TimeUnit)
  	 */
  	@Override
  	public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException
  	{
  		if (tasks.isEmpty()) return Collections.emptyList();
  
  		long end = (timeout == Long.MAX_VALUE) ? 0 : System.currentTimeMillis() + unit.toMillis(timeout);
  		boolean synchronous = !this.reverse;
  		int remaining = tasks.size();
  		LinkedList<Future<T>> futures = new LinkedList<>();
  		
  		for (Callable<T> task: this.reverse ? new Reversed<>(new ArrayList<>(tasks)) : tasks)
  		{
  			remaining -= 1;
  
  			if (synchronous)
  			{
  				Future<T> future = this.reverse ? new LazyFuture<>(task) : new EagerFuture<>(task);
  				
  				if (this.reverse)
  				{
  					futures.addFirst(future);
  				}
  				else
  				{
  					futures.addLast(future);
  				}
  				
  				// Execute remaining tasks in parallel, if there are multiple
  				if (remaining > 1)
  				{
  					synchronous = false;
  				}
  			}
  			else
  			{
  				Future<T> future = this.executor.submit(task);
  				if (this.reverse)
  				{
  					futures.addFirst(future);
  				}
  				else
  				{
  					futures.addLast(future);
  				}
  				
  				if (this.reverse && (remaining == 1))
  				{
  					synchronous = true;
  				}
  			}
  		}
  		
  		try
  		{
  			// Wait until all tasks have finished
  			for (Future<T> future: this.reverse ? new Reversed<>(futures) : futures)
  			{
  				if (!future.isDone())
  				{
  					try
  					{
  						if (end == 0)
  						{
  							future.get();
  						}
  						else
  						{
  							long now = System.currentTimeMillis();
  							if (now < end)
  							{
  								future.get(end - now, TimeUnit.MILLISECONDS);
  							}
  						}
  					}
  					catch (ExecutionException e)
  					{
  						// Ignore
  					}
  					catch (CancellationException e)
  					{
  						// Ignore
  					}
  				}
  			}
  		}
  		catch (TimeoutException e)
  		{
  			// Ignore
  		}
  		finally
  		{
  			// If interrupted, cancel any unfinished tasks
  			for (Future<T> future: this.reverse ? new Reversed<>(futures) : futures)
  			{
  				if (!future.isDone())
  				{
  					future.cancel(true);
  				}
  			}
  		}
  		
  		return futures;
  	}
  	
  	/**
  	 * {@inheritDoc}
  	 * @see java.util.concurrent.AbstractExecutorService#invokeAny(java.util.Collection)
  	 */
  	@Override
  	public <T> T invokeAny(Collection<? extends Callable<T>> tasks) throws InterruptedException, ExecutionException
  	{
  		return this.getAny(this.invokeAll(tasks));
  	}
  
  	/**
  	 * {@inheritDoc}
  	 * @see java.util.concurrent.AbstractExecutorService#invokeAny(java.util.Collection, long, java.util.concurrent.TimeUnit)
  	 */
  	@Override
  	public <T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException, ExecutionException
  	{
  		return this.getAny(this.invokeAll(tasks, timeout, unit));
  	}
  
  	private <T> T getAny(List<Future<T>> futures) throws InterruptedException, ExecutionException
  	{
  		if (futures.isEmpty()) throw new IllegalArgumentException();
  		
  		return futures.get(this.reverse ? (futures.size() - 1) : 0).get();
  	}
  	
  	/**
  	 * Future that doesn't execute its task until get(...).
  	 */
  	private static class LazyFuture<T> implements Future<T>
  	{
  		private enum State
  		{
  			NEW, CANCELLED, DONE;
  		}
  		private final Callable<T> task;
  		private volatile T result;
  		private volatile ExecutionException exception;
  		private final AtomicReference<State> state = new AtomicReference<>(State.NEW);
  		private final CountDownLatch latch = new CountDownLatch(1);
  		
  		LazyFuture(Callable<T> task)
  		{
  			this.task = task;
  		}
  
  		/**
  		 * {@inheritDoc}
  		 * @see java.util.concurrent.Future#cancel(boolean)
  		 */
  		@Override
  		public boolean cancel(boolean interrupt)
  		{
  			return this.state.compareAndSet(State.NEW, State.CANCELLED);
  		}
  
  		/**
  		 * {@inheritDoc}
  		 * @see java.util.concurrent.Future#get()
  		 */
  		@Override
  		public T get() throws ExecutionException, InterruptedException
  		{
  			return this.get(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
  		}
  
  		/**
  		 * {@inheritDoc}
  		 * @see java.util.concurrent.Future#get(long, java.util.concurrent.TimeUnit)
  		 */
  		@Override
  		public T get(long time, TimeUnit unit) throws ExecutionException, InterruptedException
  		{
  			if (this.state.compareAndSet(State.NEW, State.DONE))
  			{
  				try
  				{
  					this.result = this.task.call();
  				}
  				catch (Throwable e)
  				{
  					this.exception = new ExecutionException(e);
  				}
  				this.latch.countDown();
  			}
  			
  			if (this.state.get() == State.CANCELLED)
  			{
  				throw new CancellationException();
  			}
  			
  			if (time == Long.MAX_VALUE)
  			{
  				this.latch.await();
  			}
  			else
  			{
  				this.latch.await(time, unit);
  			}
  			
  			if (this.exception != null)
  			{
  				throw this.exception;
  			}
  			
  			return this.result;
  		}
  
  		/**
  		 * {@inheritDoc}
  		 * @see java.util.concurrent.Future#isCancelled()
  		 */
  		@Override
  		public boolean isCancelled()
  		{
  			return this.state.get() == State.CANCELLED;
  		}
  
  		/**
  		 * {@inheritDoc}
  		 * @see java.util.concurrent.Future#isDone()
  		 */
  		@Override
  		public boolean isDone()
  		{
  