Skip to content

Instantly share code, notes, and snippets.

@aikar
Created February 12, 2014 08:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aikar/8951739 to your computer and use it in GitHub Desktop.
Save aikar/8951739 to your computer and use it in GitHub Desktop.
package com.empireminecraft.util;
import org.bukkit.Bukkit;
import java.util.concurrent.ConcurrentLinkedQueue;
public class TaskChain {
// Tells a task it will perform call back later.
public static final Object WAIT = new Object();
ConcurrentLinkedQueue<Task> chainQueue = new ConcurrentLinkedQueue<>();
boolean executed = false;
Object previous = null;
boolean async = !Bukkit.isPrimaryThread();
public static TaskChain newChain() {
return new TaskChain();
}
public TaskChain delay(final int ticks) {
add(new GenericTask() {
@Override
public Object run(final Object arg) {
final GenericTask task = this;
task.chain.async = false;
BukkitUtil.scheduleTask(new Runnable() {
@Override
public void run() {
task.next(arg);
}
}, ticks);
return WAIT;
}
});
return this;
}
public TaskChain add(Task task) {
synchronized (this) {
if (executed) {
throw new RuntimeException("TaskChain is executing");
}
}
chainQueue.add(task);
return this;
}
public void execute() {
synchronized (this) {
if (executed) {
throw new RuntimeException("Already executed");
}
executed = true;
}
nextTask();
}
private void nextTask() {
final TaskChain chain = this;
final Task task = chainQueue.poll();
if (task == null) {
// done!
return;
}
if (task.async) {
if (async) {
task.run(this);
} else {
BukkitUtil.runTaskAsync(new Runnable() {
@Override
public void run() {
chain.async = true;
task.run(chain);
}
});
}
} else {
if (async) {
BukkitUtil.runTask(new Runnable() {
@Override
public void run() {
chain.async = false;
task.run(chain);
}
});
} else {
task.run(this);
}
}
}
public abstract static class Task<R, A> {
TaskChain chain = null;
boolean async = false;
private void run(TaskChain chain) {
final Object arg = chain.previous;
chain.previous = null;
this.chain = chain;
chain.previous = this.run((A) arg);
if (chain.previous != WAIT) {
chain.nextTask();
}
}
public abstract R run(A arg);
public void next(R resp) {
chain.previous = resp;
chain.nextTask();
}
}
public abstract static class GenericTask extends Task<Object, Object> {}
public abstract static class FirstTask<R> extends Task<R, Object> {}
public abstract static class LastTask<A> extends Task<Object, A> {}
public abstract static class AsyncTask<R, A> extends Task<R, A> {{async = true;}}
public abstract static class AsyncGenericTask extends GenericTask {{async = true;}}
public abstract static class AsyncFirstTask<R> extends FirstTask<R> {{async = true;}}
public abstract static class AsyncLastTask<A> extends LastTask<A> {{async = true;}}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment