<commit_before>package de.isibboi.agentsim.game;

import java.util.Collection;
import java.util.LinkedList;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import de.isibboi.agentsim.Settings;
import de.isibboi.agentsim.game.entities.Entity;

/**
 * @author <NAME>
 * @since 
 *
 */
public class MultiThreadedEntityCollider implements EntityCollider {
	private static class CollisionExecutor implements Runnable {
		private final Entity _a;
		private final Entity _b;

		/**
		 * Creates a new {@link CollisionExecutor} to evaluate the collision between the given entities.
		 * 
		 * @param a The first entity.
		 * @param b The second entity.
		 */
		public CollisionExecutor(final Entity a, final Entity b) {
			_a = a;
			_b = b;
		}

		@Override
		public void run() {
			synchronized (_a) {
				synchronized (_b) {
					_a.collideWith(_b);
				}
			}
		}
	}

	private final Logger _log = LogManager.getLogger(getClass());

	private final ThreadPoolExecutor _executor;
	private final Collection<Future<?>> _futures;
	private volatile boolean _shutdown = false;

	/**
	 * Creates a new {@link MultiThreadedEntityCollider}.
	 * The amount of threads is read from the settings.
	 * 
	 * @param settings The settings.
	 */
	public MultiThreadedEntityCollider(final Settings settings) {
		final int threadAmount = settings.getInt(Settings.CORE_UPDATE_COLLISION_THREAD_COUNT);
		_executor = new ThreadPoolExecutor(threadAmount, threadAmount, 0, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
		_executor.prestartAllCoreThreads();
		_futures = new LinkedList<>();
	}

	@Override
	public void startCollision() {
		// Do nothing.
	}

	@Override
	public void collide(final Entity a, final Entity b) {
		_futures.add(_executor.submit(new CollisionExecutor(a, b)));
	}

	@Override
	public void finishBlock() {
		// Do nothing.
	}

	@Override
	public void finishCollision() {
		try {
			for (Future<?> future : _futures) {
				future.get();
			}
		} catch (InterruptedException | ExecutionException e) {
			_log.error("Could not finish collision evaluation", e);
		}

		if (_shutdown) {
			_executor.shutdown();
		}
	}

	@Override
	public void shutdown() {
		_shutdown = true;
	}
}<commit_msg>Added log messages to MultiThreadedEntityCollider<commit_after>package de.isibboi.agentsim.game;

import java.util.Collection;
import java.util.LinkedList;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import de.isibboi.agentsim.Settings;
import de.isibboi.agentsim.game.entities.Entity;

/**
 * @author <NAME>
 * @since 
 *
 */
public class MultiThreadedEntityCollider implements EntityCollider {
	private static class CollisionExecutor implements Runnable {
		private final Entity _a;
		private final Entity _b;

		/**
		 * Creates a new {@link CollisionExecutor} to evaluate the collision between the given entities.
		 * 
		 * @param a The first entity.
		 * @param b The second entity.
		 */
		public CollisionExecutor(final Entity a, final Entity b) {
			_a = a;
			_b = b;
		}

		@Override
		public void run() {
			synchronized (_a) {
				synchronized (_b) {
					_a.collideWith(_b);
				}
			}
		}
	}

	private final Logger _log = LogManager.getLogger(getClass());

	private final ThreadPoolExecutor _executor;
	private final Collection<Future<?>> _futures;
	private volatile boolean _shutdown = false;

	/**
	 * Creates a new {@link MultiThreadedEntityCollider}.
	 * The amount of threads is read from the settings.
	 * 
	 * @param settings The settings.
	 */
	public MultiThreadedEntityCollider(final Settings settings) {
		final int threadAmount = settings.getInt(Settings.CORE_UPDATE_COLLISION_THREAD_COUNT);
		_executor = new ThreadPoolExecutor(threadAmount, threadAmount, 0, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
		_executor.prestartAllCoreThreads();
		_futures = new LinkedList<>();

		_log.info("Entity collider threads started");
	}

	@Override
	public void startCollision() {
		// Do nothing.
	}

	@Override
	public void collide(final Entity a, final Entity b) {
		_futures.add(_executor.submit(new CollisionExecutor(a, b)));
	}

	@Override
	public void finishBlock() {
		// Do nothing.
	}

	@Override
	public void finishCollision() {
		try {
			for (Future<?> future : _futures) {
				future.get();
			}
		} catch (InterruptedException | ExecutionException e) {
			_log.error("Could not finish collision evaluation", e);
		}

		if (_shutdown) {
			_executor.shutdown();
			_log.info("Entity collider thread pool is shutting down");
		}
	}

	@Override
	public void shutdown() {
		_shutdown = true;
		_log.info("Entity collider received shutdown request");
	}
}
{'fraction_non_alphanumeric': 0.10421155729676787, 'fraction_numerical': 0.0011753183153770813, 'mean_word_length': 4.157575757575757, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '983636', 'n_tokens_mistral': 1742, 'n_tokens_neox': 1573, 'n_words': 416}