Created
February 12, 2014 08:15
-
-
Save aikar/8951739 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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