// Path: src/engine/util/task/Boundaries.java
// public final class Boundaries {
// 
//   private int lowerXBound, upperXBound, lowerYBound, upperYBound;
// 
//   /**
//    * Constructs boundaries where both axis have the same ranges.
//    *
//    * @param lowerBound The lower bounds
//    * @param upperBound The upper bounds
//    */
//   public Boundaries(int lowerBound, int upperBound) {
//     this(lowerBound, upperBound, lowerBound, upperBound);
//   }
// 
//   public Boundaries(int lowerXBound, int upperXBound, int lowerYBound, int upperYBound) {
// 
//     if (lowerXBound < 0 || upperXBound < 0) {
//       throw new IllegalArgumentException("Can't have negative bounds");
//     }
//     if (lowerYBound < 0 || upperYBound < 0) {
//       throw new IllegalArgumentException("Can't have negative bounds");
//     }
// 
//     this.lowerXBound = lowerXBound;
//     this.upperXBound = upperXBound;
//     this.lowerYBound = lowerYBound;
//     this.upperYBound = upperYBound;
//   }
// 
//   public int getLowerXBound() {
//     return lowerXBound;
//   }
// 
//   public int getLowerYBound() {
//     return lowerYBound;
//   }
// 
//   public int getUpperXBound() {
//     return upperXBound;
//   }
// 
//   public int getUpperYBound() {
//     return upperYBound;
//   }
// 
// }
// 
// Path: src/engine/util/task/Task.java
// public abstract class Task {
// 
//   /**
//    * A public, mutable, reference to the thread working on this task. If this
//    * object reference is null then this task is not part of a TaskFactory.
//    */
//   private MThread parentThread = null;
//   
//   /**
//    * Marks this Task as being a single task to run only once. By default
//    * this is set to false.
//    */
//   protected boolean singleTask = false;
// 
//   public void setThread(MThread thread) {
//     parentThread = thread;
//   }
// 
//   public final MThread getThread() {
//     return parentThread;
//   }
// 
//   public boolean isNotChildCell(Cell cell) {
//     return cell.getParentThread() != parentThread;
//   }
// 
//   public boolean isSingleTask() {
//     return singleTask;
//   }
//   
//   /**
//    * This method is called when a task is added to a TaskManager. This method is
//    * used because in some instances the rest of the framework hasn't been
//    * initialized yet. CompoundTasks that add subtasks would use this method
//    * instead of a constructor, otherwise the constructor is called then
//    * this method is called.
//    */
//   public abstract void construct();
// 
//   /**
//    * This method is called before updating each cell on the surface. If this
//    * method returns false then perform on the current frame won't be called.
//    *
//    * @return true if <code>perform(x, y)</code> is to be invoked, false will
//    * skip the current frame.
//    * @throws java.lang.Exception
//    */
//   public abstract boolean check() throws Exception;
// 
//   /**
//    * An optional before-processing method called before all calls to perform(x,
//    * y) or the single call to perform() finishes.
//    */
//   public abstract void before() throws Exception;
// 
//   /**
//    * This method will be called for each cell on the surface. This method will
//    * only be called if <code>check()</code> returns true. Both x and y are
//    * bounded by [0, w) where w is the width of the map.
//    *
//    * @param x The x coordinate of the cell.
//    * @param y The y coordinate of the cell.
//    */
//   public abstract void perform(int x, int y) throws Exception;
// 
//   /**
//    * An optional after-processing method called after all calls to perform(x, y)
//    * or the single call to perform() finishes.
//    */
//   public abstract void after() throws Exception;
// 
// }
// 
// Path: src/engine/util/task/TaskManager.java
// public class TaskManager {
// 
//   private final List<Task> tasks;
//   protected Boundaries bounds;
// 
//   public TaskManager(Boundaries bounds) {
//     tasks = new ArrayList<>();
//     this.bounds = bounds;
//   }
// 
//   /**
//    * Adding a task to a manager will invoke the Task's 'construct' method.
//    *
//    * @param task The task being added to this manager.
//    */
//   public void addTask(Task task) {
//     task.construct();
//     tasks.add(task);
//   }
// 
//   public Boundaries getBounds() {
//     return bounds;
//   }
// 
//   public void performTasks() throws Exception {
//     int lowerYBound = bounds.getLowerYBound();
//     int upperYBound = bounds.getUpperYBound();
//     int lowerXBound = bounds.getLowerXBound();
//     int upperXBound = bounds.getUpperXBound();
// 
//     for (Task task : tasks) {
//       if (task.check()) {
//         task.before();
// 
//         for (int x = lowerXBound; x < upperXBound; x++) {
//           for (int y = lowerYBound; y < upperYBound; y++){
//             task.perform(x, y);
//           }
//         }
//         task.after();
//       }
//     }
//   }
// 
//   public void trimTasks() {
//     tasks.removeIf(task -> task.isSingleTask());
//   }
// }


import java.util.concurrent.CyclicBarrier;
import engine.util.task.Boundaries;
import engine.util.task.Task;
import engine.util.task.TaskManager;
import java.util.concurrent.ConcurrentLinkedDeque;
package engine.util.concurrent;


/**
 * A surface can be broken up into sections where a MThread can modify and
 control that section.
 *
 * @author Richard DeSilvey
 */
public class MThread extends TaskRunner {

  private final TaskManager manager;
  /**
   * Other threads may want to update or apply an event to other cells
   * not belonging to that thread. The other thread will post an update to
   * this thread to process the event using the queue.
   */
  private final ConcurrentLinkedDeque<Event> eventQueue;
  
  private static final boolean CONTINUOUS = true;

  private final CyclicBarrier waitingGate;

  public MThread(int delay) {
// Path: src/engine/util/task/Boundaries.java
// public final class Boundaries {
// 
//   private int lowerXBound, upperXBound, lowerYBound, upperYBound;
// 
//   /**
//    * Constructs boundaries where both axis have the same ranges.
//    *
//    * @param lowerBound The lower bounds
//    * @param upperBound The upper bounds
//    */
//   public Boundaries(int lowerBound, int upperBound) {
//     this(lowerBound, upperBound, lowerBound, upperBound);
//   }
// 
//   public Boundaries(int lowerXBound, int upperXBound, int lowerYBound, int upperYBound) {
// 
//     if (lowerXBound < 0 || upperXBound < 0) {
//       throw new IllegalArgumentException("Can't have negative bounds");
//     }
//     if (lowerYBound < 0 || upperYBound < 0) {
//       throw new IllegalArgumentException("Can't have negative bounds");
//     }
// 
//     this.lowerXBound = lowerXBound;
//     this.upperXBound = upperXBound;
//     this.lowerYBound = lowerYBound;
//     this.upperYBound = upperYBound;
//   }
// 
//   public int getLowerXBound() {
//     return lowerXBound;
//   }
// 
//   public int getLowerYBound() {
//     return lowerYBound;
//   }
// 
//   public int getUpperXBound() {
//     return upperXBound;
//   }
// 
//   public int getUpperYBound() {
//     return upperYBound;
//   }
// 
// }
// 
// Path: src/engine/util/task/Task.java
// public abstract class Task {
// 
//   /**
//    * A public, mutable, reference to the thread working on this task. If this
//    * object reference is null then this task is not part of a TaskFactory.
//    */
//   private MThread parentThread = null;
//   
//   /**
//    * Marks this Task as being a single task to run only once. By default
//    * this is set to false.
//    */
//   protected boolean singleTask = false;
// 
//   public void setThread(MThread thread) {
//     parentThread = thread;
//   }
// 
//   public final MThread getThread() {
//     return parentThread;
//   }
// 
//   public boolean isNotChildCell(Cell cell) {
//     return cell.getParentThread() != parentThread;
//   }
// 
//   public boolean isSingleTask() {
//     return singleTask;
//   }
//   
//   /**
//    * This method is called when a task is added to a TaskManager. This method is
//    * used because in some instances the rest of the framework hasn't been
//    * initialized yet. CompoundTasks that add subtasks would use this method
//    * instead of a constructor, otherwise the constructor is called then
//    * this method is called.
//    */
//   public abstract void construct();
// 
//   /**
//    * This method is called before updating each cell on the surface. If this
//    * method returns false then perform on the current frame won't be called.
//    *
//    * @return true if <code>perform(x, y)</code> is to be invoked, false will
//    * skip the current frame.
//    * @throws java.lang.Exception
//    */
//   public abstract boolean check() throws Exception;
// 
//   /**
//    * An optional before-processing method called before all calls to perform(x,
//    * y) or the single call to perform() finishes.
//    */
//   public abstract void before() throws Exception;
// 
//   /**
//    * This method will be called for each cell on the surface. This method will
//    * only be called if <code>check()</code> returns true. Both x and y are
//    * bounded by [0, w) where w is the width of the map.
//    *
//    * @param x The x coordinate of the cell.
//    * @param y The y coordinate of the cell.
//    */
//   public abstract void perform(int x, int y) throws Exception;
// 
//   /**
//    * An optional after-processing method called after all calls to perform(x, y)
//    * or the single call to perform() finishes.
//    */
//   public abstract void after() throws Exception;
// 
// }
// 
// Path: src/engine/util/task/TaskManager.java
// public class TaskManager {
// 
//   private final List<Task> tasks;
//   protected Boundaries bounds;
// 
//   public TaskManager(Boundaries bounds) {
//     tasks = new ArrayList<>();
//     this.bounds = bounds;
//   }
// 
//   /**
//    * Adding a task to a manager will invoke the Task's 'construct' method.
//    *
//    * @param task The task being added to this manager.
//    */
//   public void addTask(Task task) {
//     task.construct();
//     tasks.add(task);
//   }
// 
//   public Boundaries getBounds() {
//     return bounds;
//   }
// 
//   public void performTasks() throws Exception {
//     int lowerYBound = bounds.getLowerYBound();
//     int upperYBound = bounds.getUpperYBound();
//     int lowerXBound = bounds.getLowerXBound();
//     int upperXBound = bounds.getUpperXBound();
// 
//     for (Task task : tasks) {
//       if (task.check()) {
//         task.before();
// 
//         for (int x = lowerXBound; x < upperXBound; x++) {
//           for (int y = lowerYBound; y < upperYBound; y++){
//             task.perform(x, y);
//           }
//         }
//         task.after();
//       }
//     }
//   }
// 
//   public void trimTasks() {
//     tasks.removeIf(task -> task.isSingleTask());
//   }
// }


// Path: src/engine/util/concurrent/MThread.java
import java.util.concurrent.CyclicBarrier;
import engine.util.task.Boundaries;
import engine.util.task.Task;
import engine.util.task.TaskManager;
import java.util.concurrent.ConcurrentLinkedDeque;

package engine.util.concurrent;


/**
 * A surface can be broken up into sections where a MThread can modify and
 control that section.
 *
 * @author Richard DeSilvey
 */
public class MThread extends TaskRunner {

  private final TaskManager manager;
  /**
   * Other threads may want to update or apply an event to other cells
   * not belonging to that thread. The other thread will post an update to
   * this thread to process the event using the queue.
   */
  private final ConcurrentLinkedDeque<Event> eventQueue;
  
  private static final boolean CONTINUOUS = true;

  private final CyclicBarrier waitingGate;

  public MThread(int delay) {
    this(delay, new Boundaries(0, 0), new CyclicBarrier(1));