From c23d7f4e06b63e0a2cc96330893eb0cf93d6a763 Mon Sep 17 00:00:00 2001 From: Wesley Wolfe Date: Sat, 6 Oct 2012 18:38:00 -0500 Subject: Add simpler API for using the scheduler. Adds BUKKIT-836 The new methods return the actual task that gets created from the scheduler. They are also named such that auto-complete puts the asynchronous methods after the normal ones. These two additions are simply semantic. Tasks now have a method to cancel themselves using their task id. This is provided as a convenience. A new class called SimpleRunnable was added. It is an abstract Runnable such that anonymous classes may subclass it. It provides six convenience methods for scheduling as appropriate. It also provides a cancel method for convenience. The functionality of SimpleRunnable only stores an integer representing the task id. A SimpleRunnable can only be scheduled once; attempting to reschedule results in IllegalStateException. --- .../java/org/bukkit/scheduler/BukkitRunnable.java | 143 +++++++++++++++++++++ .../java/org/bukkit/scheduler/BukkitScheduler.java | 95 +++++++++++++- src/main/java/org/bukkit/scheduler/BukkitTask.java | 5 + 3 files changed, 240 insertions(+), 3 deletions(-) create mode 100644 src/main/java/org/bukkit/scheduler/BukkitRunnable.java (limited to 'src') diff --git a/src/main/java/org/bukkit/scheduler/BukkitRunnable.java b/src/main/java/org/bukkit/scheduler/BukkitRunnable.java new file mode 100644 index 00000000..15e0d688 --- /dev/null +++ b/src/main/java/org/bukkit/scheduler/BukkitRunnable.java @@ -0,0 +1,143 @@ +package org.bukkit.scheduler; + +import org.bukkit.Bukkit; +import org.bukkit.plugin.Plugin; + +/** + * This class is provided as an easy way to handle scheduling tasks. + */ +public abstract class BukkitRunnable implements Runnable { + private int taskId = -1; + + /** + * Attempts to cancel this task + * @throws IllegalStateException if task was not scheduled yet + */ + public synchronized void cancel() throws IllegalStateException { + Bukkit.getScheduler().cancelTask(getTaskId()); + } + + /** + * Schedules this in the Bukkit scheduler to run on next tick + * + * @param plugin the reference to the plugin scheduling task + * @return a BukkitTask that contains the id number + * @throws IllegalArgumentException if plugin is null + * @throws IllegalStateException if this was already scheduled + * @see BukkitScheduler#runTask(Plugin, Runnable) + */ + public synchronized BukkitTask runTask(Plugin plugin) throws IllegalArgumentException, IllegalStateException { + checkState(); + return setupId(Bukkit.getScheduler().runTask(plugin, this)); + } + + /** + * Asynchronous tasks should never access any API in Bukkit. + * Great care should be taken to assure the thread-safety of asynchronous tasks. + *
+ *
Schedules this in the Bukkit scheduler to run asynchronously. + * + * @param plugin the reference to the plugin scheduling task + * @return a BukkitTask that contains the id number + * @throws IllegalArgumentException if plugin is null + * @throws IllegalStateException if this was already scheduled + * @see BukkitScheduler#runTaskAsynchronously(Plugin, Runnable, long, long) + */ + public synchronized BukkitTask runTaskAsynchronously(Plugin plugin) throws IllegalArgumentException, IllegalStateException { + checkState(); + return setupId(Bukkit.getScheduler().runTaskAsynchronously(plugin, this)); + } + + /** + * Schedules this to run after the specified number of server ticks. + * + * @param plugin the reference to the plugin scheduling task + * @param task the task to be run + * @param delay the ticks to wait before running the task + * @return a BukkitTask that contains the id number + * @throws IllegalArgumentException if plugin is null + * @throws IllegalStateException if this was already scheduled + * @see BukkitScheduler#runTaskLater(Plugin, Runnable, long, long) + */ + public synchronized BukkitTask runTaskLater(Plugin plugin, long delay) throws IllegalArgumentException, IllegalStateException { + checkState(); + return setupId(Bukkit.getScheduler().runTaskLater(plugin, this, delay)); + } + + /** + * Asynchronous tasks should never access any API in Bukkit. + * Great care should be taken to assure the thread-safety of asynchronous tasks. + *
+ *
Schedules this to run asynchronously after the specified number of server ticks. + * + * @param plugin the reference to the plugin scheduling task + * @param delay the ticks to wait before running the task + * @return a BukkitTask that contains the id number + * @throws IllegalArgumentException if plugin is null + * @throws IllegalStateException if this was already scheduled + * @see BukkitScheduler#runTaskLaterAsynchronously(Plugin, Runnable, long, long) + */ + public synchronized BukkitTask runTaskLaterAsynchronously(Plugin plugin, long delay) throws IllegalArgumentException, IllegalStateException { + checkState(); + return setupId(Bukkit.getScheduler().runTaskLaterAsynchronously(plugin, this, delay)); + } + + /** + * Schedules this to repeatedly run until cancelled, starting after the specified number of server ticks + * + * @param plugin the reference to the plugin scheduling task + * @param delay the ticks to wait before running the task + * @param period the ticks to wait between runs + * @return a BukkitTask that contains the id number + * @throws IllegalArgumentException if plugin is null + * @throws IllegalStateException if this was already scheduled + * @see BukkitScheduler#runTaskTimer(Plugin, Runnable, long, long) + */ + public synchronized BukkitTask runTaskTimer(Plugin plugin, long delay, long period) throws IllegalArgumentException, IllegalStateException { + checkState(); + return setupId(Bukkit.getScheduler().runTaskTimer(plugin, this, delay, period)); + } + + /** + * Asynchronous tasks should never access any API in Bukkit. + * Great care should be taken to assure the thread-safety of asynchronous tasks. + *
+ *
Schedules this to repeatedly run asynchronously until cancelled, starting after the specified number of server ticks. + * + * @param plugin the reference to the plugin scheduling task + * @param delay the ticks to wait before running the task for the first time + * @param period the ticks to wait between runs + * @return a BukkitTask that contains the id number + * @throws IllegalArgumentException if plugin is null + * @throws IllegalStateException if this was already scheduled + * @see BukkitScheduler#runTaskTimerAsynchronously(Plugin, Runnable, long, long) + */ + public synchronized BukkitTask runTaskTimerAsynchronously(Plugin plugin, long delay, long period) throws IllegalArgumentException, IllegalStateException { + checkState(); + return setupId(Bukkit.getScheduler().runTaskTimerAsynchronously(plugin, this, delay, period)); + } + + /** + * Gets the task id for this runnable + * @return the task id that this runnable was scheduled as + * @throws IllegalStateException if task was not scheduled yet + */ + public synchronized int getTaskId() throws IllegalStateException { + final int id = taskId; + if (id == -1) { + throw new IllegalStateException("Not scheduled yet"); + } + return id; + } + + private void checkState() { + if (taskId != -1) { + throw new IllegalStateException("Already scheduled as " + taskId); + } + } + + private BukkitTask setupId(final BukkitTask task) { + this.taskId = task.getTaskId(); + return task; + } +} diff --git a/src/main/java/org/bukkit/scheduler/BukkitScheduler.java b/src/main/java/org/bukkit/scheduler/BukkitScheduler.java index 4477c56d..86b0db97 100644 --- a/src/main/java/org/bukkit/scheduler/BukkitScheduler.java +++ b/src/main/java/org/bukkit/scheduler/BukkitScheduler.java @@ -41,7 +41,10 @@ public interface BukkitScheduler { public int scheduleSyncRepeatingTask(Plugin plugin, Runnable task, long delay, long period); /** - * Schedules a once off task to occur after a delay + * Asynchronous tasks should never access any API in Bukkit. + * Great care should be taken to assure the thread-safety of asynchronous tasks. + *
+ *
Schedules a once off task to occur after a delay, * This task will be executed by a thread managed by the scheduler * * @param plugin Plugin that owns the task @@ -52,7 +55,10 @@ public interface BukkitScheduler { public int scheduleAsyncDelayedTask(Plugin plugin, Runnable task, long delay); /** - * Schedules a once off task to occur as soon as possible + * Asynchronous tasks should never access any API in Bukkit. + * Great care should be taken to assure the thread-safety of asynchronous tasks. + *
+ *
Schedules a once off task to occur as soon as possible. * This task will be executed by a thread managed by the scheduler * * @param plugin Plugin that owns the task @@ -62,7 +68,10 @@ public interface BukkitScheduler { public int scheduleAsyncDelayedTask(Plugin plugin, Runnable task); /** - * Schedules a repeating task + * Asynchronous tasks should never access any API in Bukkit. + * Great care should be taken to assure the thread-safety of asynchronous tasks. + *
+ *
Schedules a repeating task. * This task will be executed by a thread managed by the scheduler * * @param plugin Plugin that owns the task @@ -148,4 +157,84 @@ public interface BukkitScheduler { */ public List getPendingTasks(); + /** + * Returns a task that will run on the next server tick. + * + * @param plugin the reference to the plugin scheduling task + * @param task the task to be run + * @return a BukkitTask that contains the id number + * @throws IllegalArgumentException if plugin is null + * @throws IllegalArgumentException if task is null + */ + public BukkitTask runTask(Plugin plugin, Runnable task) throws IllegalArgumentException; + + /** + * Asynchronous tasks should never access any API in Bukkit. + * Great care should be taken to assure the thread-safety of asynchronous tasks. + *
+ *
Returns a task that will run asynchronously. + * + * @param plugin the reference to the plugin scheduling task + * @param task the task to be run + * @return a BukkitTask that contains the id number + * @throws IllegalArgumentException if plugin is null + * @throws IllegalArgumentException if task is null + */ + public BukkitTask runTaskAsynchronously(Plugin plugin, Runnable task) throws IllegalArgumentException; + + /** + * Returns a task that will run after the specified number of server ticks. + * + * @param plugin the reference to the plugin scheduling task + * @param task the task to be run + * @param delay the ticks to wait before running the task + * @return a BukkitTask that contains the id number + * @throws IllegalArgumentException if plugin is null + * @throws IllegalArgumentException if task is null + */ + public BukkitTask runTaskLater(Plugin plugin, Runnable task, long delay) throws IllegalArgumentException; + + /** + * Asynchronous tasks should never access any API in Bukkit. + * Great care should be taken to assure the thread-safety of asynchronous tasks. + *
+ *
Returns a task that will run asynchronously after the specified number of server ticks. + * + * @param plugin the reference to the plugin scheduling task + * @param task the task to be run + * @param delay the ticks to wait before running the task + * @return a BukkitTask that contains the id number + * @throws IllegalArgumentException if plugin is null + * @throws IllegalArgumentException if task is null + */ + public BukkitTask runTaskLaterAsynchronously(Plugin plugin, Runnable task, long delay) throws IllegalArgumentException; + + /** + * Returns a task that will repeatedly run until cancelled, starting after the specified number of server ticks + * + * @param plugin the reference to the plugin scheduling task + * @param task the task to be run + * @param delay the ticks to wait before running the task + * @param period the ticks to wait between runs + * @return a BukkitTask that contains the id number + * @throws IllegalArgumentException if plugin is null + * @throws IllegalArgumentException if task is null + */ + public BukkitTask runTaskTimer(Plugin plugin, Runnable task, long delay, long period) throws IllegalArgumentException; + + /** + * Asynchronous tasks should never access any API in Bukkit. + * Great care should be taken to assure the thread-safety of asynchronous tasks. + *
+ *
Returns a task that will repeatedly run asynchronously until cancelled, starting after the specified number of server ticks. + * + * @param plugin the reference to the plugin scheduling task + * @param task the task to be run + * @param delay the ticks to wait before running the task for the first time + * @param period the ticks to wait between runs + * @return a BukkitTask that contains the id number + * @throws IllegalArgumentException if plugin is null + * @throws IllegalArgumentException if task is null + */ + public BukkitTask runTaskTimerAsynchronously(Plugin plugin, Runnable task, long delay, long period) throws IllegalArgumentException; } diff --git a/src/main/java/org/bukkit/scheduler/BukkitTask.java b/src/main/java/org/bukkit/scheduler/BukkitTask.java index f82514cf..17ea1fae 100644 --- a/src/main/java/org/bukkit/scheduler/BukkitTask.java +++ b/src/main/java/org/bukkit/scheduler/BukkitTask.java @@ -28,4 +28,9 @@ public interface BukkitTask { * @return true if the task is run by main thread */ public boolean isSync(); + + /** + * Will attempt to cancel this task + */ + public void cancel(); } -- cgit v1.2.3