/*
 * Encog(tm) Core v2.5 - Java Version
 * http://www.heatonresearch.com/encog/
 * http://code.google.com/p/encog-java/
 
 * Copyright 2008-2010 Heaton Research, Inc.
 *
 * 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.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *   
 * For more information on Heaton Research copyrights, licenses 
 * and trademarks visit:
 * http://www.heatonresearch.com/copyright
 */

package org.encog.engine.concurrency;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import org.encog.engine.EncogEngineError;

/**
 * This class abstracts thread pools, and potentially grids and other types of
 * concurrency. It is used by other classes inside of Encog to allow tasks to be
 * executed efficiently on multicore machines.
 * 
 * @author jheaton
 * 
 */
public class EngineConcurrency {

	/**
	 * Singleton instance.
	 */
	private static EngineConcurrency instance;

	/**
	 * @return The instance to the singleton.
	 */
	public static EngineConcurrency getInstance() {
		if (EngineConcurrency.instance == null) {
			EngineConcurrency.instance = new EngineConcurrency();
		}
		return EngineConcurrency.instance;
	}

	/**
<<<<<<< .mine
	 * An error that was caught in one of the threads. Will be thrown by the
	 * main thread.
	 */
	private Throwable threadError;

	/**
=======
>>>>>>> .r1927
	 * The current task group, used to ensure that all threads finish at the
	 * same time.
	 */
	private int currentTaskGroup;

	/**
	 * The executor service we are using.
	 */
	private ExecutorService executor;

	/**
	 * Construct a concurrency object.
	 */
	public EngineConcurrency() {
		this.executor = Executors.newFixedThreadPool(100);
	}

	/**
	 * Check to see if one of the threads has thrown an error. If so, then throw
	 * that error.
	 */
	public void checkError() {
		if (this.threadError != null) {
			throw new EncogEngineError(this.threadError);
		}
	}
	
	/**
	 * Create a new task group.
	 * @return The new task group.
	 */
	public TaskGroup createTaskGroup() {
		TaskGroup result = null;
		synchronized (this) {
			this.currentTaskGroup++;
			result = new TaskGroup(this.currentTaskGroup);

		}
		return result;
	}

	/**
	 * Process the specified task.
	 * @param task The task to process.
	 */
	public void processTask(final EngineTask task) {
		processTask(task, null);
	}

	/**
	 * Process the specified task. It will be processed either now, or queued to
	 * process on the thread pool.
	 * 
	 * @param task
	 *            The task to process.
	 * @param group The task group.
	 */
	public void processTask(final EngineTask task, final TaskGroup group) {
		if (this.executor == null) {
			task.run();
		} else {
			if (this.threadError != null) {
				final Throwable t = this.threadError;
				this.threadError = null;
				throw new EncogEngineError(t);
			}

			final PoolItem item = new PoolItem(task, group);
			if (group != null) {
				group.taskStarting();
			}
			this.executor.execute(item);
		}
	}

	/**
	 * Allows threads to register errors, these errors will be thrown by the
	 * main thread.
	 * 
	 * @param t
	 *            The error to register.
	 */
	public void registerError(final Throwable t) {
		synchronized (this) {
			this.threadError = t;
		}

	}

	/**
	 * Wait for all threads in the pool to complete.
	 * 
	 * @param timeout
	 *            How long to wait for all threads to complete.
	 */
	public void shutdown(final long timeout) {
		if (this.executor != null) {
			try {
				this.executor.shutdown();
				this.executor.awaitTermination(timeout, TimeUnit.SECONDS);
				this.executor = null;
			} catch (final InterruptedException e) {
				throw new EncogEngineError(e);
			}
		}
	}
}

@@ -2250,11 +2250,12 @@
 .new
-Fix
+Cach
 edTh
@@ -2267,11 +2267,8 @@
 ool(
-100
 );%0D%0A

Use dynamic threadpool.