Close async tasks properly when shutting down
This commit is contained in:
parent
62ec9c99ef
commit
b47db98420
4 changed files with 83 additions and 23 deletions
|
|
@ -12,12 +12,17 @@ public class BukkitTaskManager extends AbstractTaskManager<BukkitTask> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void runTask(Runnable runnable) {
|
protected BukkitTask runTaskImpl(Runnable runnable) {
|
||||||
addTask(Bukkit.getScheduler().runTask(ServerUtils.getInstance(), runnable));
|
return Bukkit.getScheduler().runTask(ServerUtils.getInstance(), runnable);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void runTaskAsynchronously(Runnable runnable) {
|
protected BukkitTask runTaskAsynchronouslyImpl(Runnable runnable) {
|
||||||
addTask(Bukkit.getScheduler().runTaskAsynchronously(ServerUtils.getInstance(), runnable));
|
return Bukkit.getScheduler().runTaskAsynchronously(ServerUtils.getInstance(), runnable);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cancelTask(BukkitTask task) {
|
||||||
|
task.cancel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,12 +12,17 @@ public class BungeeTaskManager extends AbstractTaskManager<ScheduledTask> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void runTask(Runnable runnable) {
|
protected ScheduledTask runTaskImpl(Runnable runnable) {
|
||||||
runTaskAsynchronously(runnable);
|
return runTaskAsynchronously(runnable);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void runTaskAsynchronously(Runnable runnable) {
|
protected ScheduledTask runTaskAsynchronouslyImpl(Runnable runnable) {
|
||||||
ProxyServer.getInstance().getScheduler().runAsync(ServerUtils.getInstance(), runnable);
|
return ProxyServer.getInstance().getScheduler().runAsync(ServerUtils.getInstance(), runnable);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cancelTask(ScheduledTask task) {
|
||||||
|
task.cancel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ public abstract class AbstractTaskManager<T> {
|
||||||
|
|
||||||
private final List<T> serverTasks;
|
private final List<T> serverTasks;
|
||||||
private final Consumer<T> taskCloser;
|
private final Consumer<T> taskCloser;
|
||||||
private final Map<String, AbstractTask> tasks;
|
private final Map<String, RunningTask> tasks;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new TaskManager with a consumer which closes a task.
|
* Constructs a new TaskManager with a consumer which closes a task.
|
||||||
|
|
@ -24,31 +24,56 @@ public abstract class AbstractTaskManager<T> {
|
||||||
this.tasks = new HashMap<>();
|
this.tasks = new HashMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract void runTask(Runnable runnable);
|
protected abstract T runTaskImpl(Runnable runnable);
|
||||||
|
|
||||||
public void runTask(String key, AbstractTask task) {
|
public T runTask(Runnable runnable) {
|
||||||
tasks.put(key, task);
|
return addTask(runTaskImpl(runnable));
|
||||||
runTask(task);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract void runTaskAsynchronously(Runnable runnable);
|
/**
|
||||||
|
* Associates a synchronous task with a key which can be cancelled later by that key.
|
||||||
public void runTaskAsynchronously(String key, AbstractTask task) {
|
* @param key The key of the task.
|
||||||
tasks.put(key, task);
|
* @param abstractTask The AbstractTask.
|
||||||
runTaskAsynchronously(task);
|
* @return The implementation-specific scheduled task.
|
||||||
|
*/
|
||||||
|
public T runTask(String key, AbstractTask abstractTask) {
|
||||||
|
T task = runTask(abstractTask);
|
||||||
|
tasks.put(key, new RunningTask(task, abstractTask));
|
||||||
|
return task;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addTask(T task) {
|
protected abstract T runTaskAsynchronouslyImpl(Runnable runnable);
|
||||||
|
|
||||||
|
public T runTaskAsynchronously(Runnable runnable) {
|
||||||
|
return addTask(runTaskAsynchronouslyImpl(runnable));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Associates an asynchronous task with a key which can be cancelled later by that key.
|
||||||
|
* @param key The key of the task.
|
||||||
|
* @param abstractTask The AbstractTask.
|
||||||
|
* @return The implementation-specific scheduled task.
|
||||||
|
*/
|
||||||
|
public T runTaskAsynchronously(String key, AbstractTask abstractTask) {
|
||||||
|
T task = runTaskAsynchronously(abstractTask);
|
||||||
|
tasks.put(key, new RunningTask(task, abstractTask));
|
||||||
|
return task;
|
||||||
|
}
|
||||||
|
|
||||||
|
private T addTask(T task) {
|
||||||
serverTasks.add(task);
|
serverTasks.add(task);
|
||||||
|
return task;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public abstract void cancelTask(T task);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cancels a single task by key.
|
* Cancels a single task by key.
|
||||||
* @param key The key of the task.
|
* @param key The key of the task.
|
||||||
* @return Whether or not the task existed.
|
* @return Whether or not the task existed.
|
||||||
*/
|
*/
|
||||||
public boolean cancelTask(String key) {
|
public boolean cancelTask(String key) {
|
||||||
AbstractTask task = tasks.remove(key);
|
RunningTask task = tasks.remove(key);
|
||||||
if (task == null) return false;
|
if (task == null) return false;
|
||||||
task.cancel();
|
task.cancel();
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -58,7 +83,7 @@ public abstract class AbstractTaskManager<T> {
|
||||||
* Cancels all tasks.
|
* Cancels all tasks.
|
||||||
*/
|
*/
|
||||||
public void cancelAllTasks() {
|
public void cancelAllTasks() {
|
||||||
for (AbstractTask task : tasks.values()) {
|
for (RunningTask task : tasks.values()) {
|
||||||
task.cancel();
|
task.cancel();
|
||||||
}
|
}
|
||||||
tasks.clear();
|
tasks.clear();
|
||||||
|
|
@ -68,4 +93,19 @@ public abstract class AbstractTaskManager<T> {
|
||||||
}
|
}
|
||||||
serverTasks.clear();
|
serverTasks.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final class RunningTask {
|
||||||
|
private final T task;
|
||||||
|
private final AbstractTask abstractTask;
|
||||||
|
|
||||||
|
private RunningTask(T task, AbstractTask abstractTask) {
|
||||||
|
this.task = task;
|
||||||
|
this.abstractTask = abstractTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void cancel() {
|
||||||
|
cancelTask(task);
|
||||||
|
abstractTask.cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import com.sun.nio.file.SensitivityWatchEventModifier;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.nio.file.ClosedWatchServiceException;
|
||||||
import java.nio.file.FileSystems;
|
import java.nio.file.FileSystems;
|
||||||
import java.nio.file.StandardWatchEventKinds;
|
import java.nio.file.StandardWatchEventKinds;
|
||||||
import java.nio.file.WatchEvent;
|
import java.nio.file.WatchEvent;
|
||||||
|
|
@ -41,6 +42,8 @@ public class PluginWatcherTask extends AbstractTask {
|
||||||
private File file;
|
private File file;
|
||||||
private final AtomicBoolean run;
|
private final AtomicBoolean run;
|
||||||
|
|
||||||
|
private WatchService watchService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new PluginWatcherTask for the specified plugin.
|
* Constructs a new PluginWatcherTask for the specified plugin.
|
||||||
* @param pluginName The name of the plugin.
|
* @param pluginName The name of the plugin.
|
||||||
|
|
@ -55,6 +58,8 @@ public class PluginWatcherTask extends AbstractTask {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
try (WatchService watchService = FileSystems.getDefault().newWatchService()) {
|
try (WatchService watchService = FileSystems.getDefault().newWatchService()) {
|
||||||
|
this.watchService = watchService;
|
||||||
|
|
||||||
File folder = pluginManager.getPluginsFolder();
|
File folder = pluginManager.getPluginsFolder();
|
||||||
folder.toPath().register(watchService, EVENTS, SensitivityWatchEventModifier.HIGH);
|
folder.toPath().register(watchService, EVENTS, SensitivityWatchEventModifier.HIGH);
|
||||||
|
|
||||||
|
|
@ -76,9 +81,9 @@ public class PluginWatcherTask extends AbstractTask {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (IOException ex) {
|
} catch (IOException | InterruptedException ex) {
|
||||||
ex.printStackTrace();
|
ex.printStackTrace();
|
||||||
} catch (InterruptedException ignored) {
|
} catch (ClosedWatchServiceException ignored) {
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -93,5 +98,10 @@ public class PluginWatcherTask extends AbstractTask {
|
||||||
@Override
|
@Override
|
||||||
public void cancel() {
|
public void cancel() {
|
||||||
run.set(false);
|
run.set(false);
|
||||||
|
try {
|
||||||
|
watchService.close();
|
||||||
|
} catch (IOException ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue