package com.asteria.task;
import java.util.ArrayDeque;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import com.google.common.base.Preconditions;
/**
* The task handler that oversees the processing of all submitted tasks. It
* makes sure tasks are stopped when requested and executed at the correct time.
* <p>
* <p>
* The data structures that hold tasks for processing are not thread safe, which
* means tasks should only be submitted on the main game thread.
*
* @author lare96 <http://github.com/lare96>
*/
public final class TaskQueue {
/**
* The list that holds all of the pending tasks that are awaiting execution.
*/
private final List<Task> pendingTasks = new LinkedList<>();
/**
* The queue that holds all of the tasks that are ready to be executed.
*/
private final Queue<Task> runTasks = new ArrayDeque<>(50);
/**
* Queues pending tasks that are ready to be executed and executes tasks
* that were previously queued.
*
* @throws Exception
* if any errors occur while processing the tasks.
*/
public void sequence() throws Exception {
Iterator<Task> $it = pendingTasks.iterator();
while ($it.hasNext()) {
Task t = $it.next();
t.onSequence();
if (t.needsExecute()) {
runTasks.add(t);
} else if (!t.isRunning()) {
$it.remove();
}
}
Task t;
while ((t = runTasks.poll()) != null) {
try {
t.execute();
} catch (Throwable ex) {
ex.printStackTrace();
t.onThrowable(ex);
}
}
}
/**
* Submits {@code task} to this task handler. The task must be running for
* it to be successfully submitted.
*
* @param task
* the task to submit to this task handler.
*/
public void submit(Task task) {
Preconditions.checkArgument(task.isRunning());
task.onSubmit();
if (task.isInstant())
task.execute();
if (task.isRunning())
pendingTasks.add(task);
}
/**
* Cancels all tasks with {@code key} as their key attachment.
*
* @param key
* the key to cancel all tasks with.
*/
public void cancel(Object key) {
pendingTasks.stream().filter(t -> t.getKey().equals(key)).forEach(t -> t.cancel());
}
}