/**
 * <p>
 * Copyright © 2009-2010, Bruce-Robert Pocock
 * </p>
 * <p>
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or (at
 * your option) any later version.
 * </p>
 * <p>
 * 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
 * General Public License for more details.
 * </p>
 * <p>
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 * </p>
 * 
 * @author brpocock
 */
package org.starhope.appius.game;

import java.util.concurrent.ConcurrentSkipListSet;

import org.starhope.appius.util.AppiusConfig;

/**
 * 
 * Charon is the reaper for zombie threads. WRITEME
 * 
 * @author brpocock
 * 
 */
public class Charon extends Thread {

	/**
	 * The time to sleep between passes reaping the zombie threads
	 */
	private final long reaperSleep = AppiusConfig.getIntOrDefault (
			"org.starhope.appius.charon.reaperSleep", 5000);
	/**
	 * The set of threads who might be zombies
	 */
	private final ConcurrentSkipListSet <Thread> restlessDead = new ConcurrentSkipListSet <Thread> ();

	/**
	 * How long to wait for a zombie to join us before passing it over
	 * for this reaper pass
	 */
	private final long threadJoinTimeout = AppiusConfig
	.getIntOrDefault (
			"org.starhope.appius.charon.threadJoinTimeout", 10);

	/**
	 * Add a thread to the pool to be checked to reaping periodically
	 * 
	 * @param t The zombie thread to be checked for reaping
	 */
	public void addZombie (final Thread t) {
		restlessDead.add (t);
	}

	/**
	 * This is an overriding method.
	 * 
	 * @see java.lang.Thread#run()
	 */
	@Override
	public void run () {
		setName ("Charon");

		while (true) {
			if (restlessDead.size () > 0) {
				for (final Thread t : restlessDead) {
					try {
						t.join (threadJoinTimeout);
					} catch (final InterruptedException e) {
						// No op. We'll be back, soon enough.
					}
				}
			}
			Thread.yield ();
			try {
				Thread.sleep (reaperSleep);
			} catch (final InterruptedException e) {
				// No op.
			}
		}
	}
}
