Close async tasks properly when shutting down

This commit is contained in:
Frank van der Heijden 2020-07-27 01:02:50 +02:00
parent 62ec9c99ef
commit b47db98420
No known key found for this signature in database
GPG key ID: 26DA56488D314D11
4 changed files with 83 additions and 23 deletions

View file

@ -12,12 +12,17 @@ public class BukkitTaskManager extends AbstractTaskManager<BukkitTask> {
}
@Override
public void runTask(Runnable runnable) {
addTask(Bukkit.getScheduler().runTask(ServerUtils.getInstance(), runnable));
protected BukkitTask runTaskImpl(Runnable runnable) {
return Bukkit.getScheduler().runTask(ServerUtils.getInstance(), runnable);
}
@Override
public void runTaskAsynchronously(Runnable runnable) {
addTask(Bukkit.getScheduler().runTaskAsynchronously(ServerUtils.getInstance(), runnable));
protected BukkitTask runTaskAsynchronouslyImpl(Runnable runnable) {
return Bukkit.getScheduler().runTaskAsynchronously(ServerUtils.getInstance(), runnable);
}
@Override
public void cancelTask(BukkitTask task) {
task.cancel();
}
}

View file

@ -12,12 +12,17 @@ public class BungeeTaskManager extends AbstractTaskManager<ScheduledTask> {
}
@Override
public void runTask(Runnable runnable) {
runTaskAsynchronously(runnable);
protected ScheduledTask runTaskImpl(Runnable runnable) {
return runTaskAsynchronously(runnable);
}
@Override
public void runTaskAsynchronously(Runnable runnable) {
ProxyServer.getInstance().getScheduler().runAsync(ServerUtils.getInstance(), runnable);
protected ScheduledTask runTaskAsynchronouslyImpl(Runnable runnable) {
return ProxyServer.getInstance().getScheduler().runAsync(ServerUtils.getInstance(), runnable);
}
@Override
public void cancelTask(ScheduledTask task) {
task.cancel();
}
}

View file

@ -12,7 +12,7 @@ public abstract class AbstractTaskManager<T> {
private final List<T> serverTasks;
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.
@ -24,31 +24,56 @@ public abstract class AbstractTaskManager<T> {
this.tasks = new HashMap<>();
}
public abstract void runTask(Runnable runnable);
protected abstract T runTaskImpl(Runnable runnable);
public void runTask(String key, AbstractTask task) {
tasks.put(key, task);
runTask(task);
public T runTask(Runnable runnable) {
return addTask(runTaskImpl(runnable));
}
public abstract void runTaskAsynchronously(Runnable runnable);
public void runTaskAsynchronously(String key, AbstractTask task) {
tasks.put(key, task);
runTaskAsynchronously(task);
/**
* Associates a synchronous 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 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);
return task;
}
public abstract void cancelTask(T task);
/**
* Cancels a single task by key.
* @param key The key of the task.
* @return Whether or not the task existed.
*/
public boolean cancelTask(String key) {
AbstractTask task = tasks.remove(key);
RunningTask task = tasks.remove(key);
if (task == null) return false;
task.cancel();
return true;
@ -58,7 +83,7 @@ public abstract class AbstractTaskManager<T> {
* Cancels all tasks.
*/
public void cancelAllTasks() {
for (AbstractTask task : tasks.values()) {
for (RunningTask task : tasks.values()) {
task.cancel();
}
tasks.clear();
@ -68,4 +93,19 @@ public abstract class AbstractTaskManager<T> {
}
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();
}
}
}

View file

@ -4,6 +4,7 @@ import com.sun.nio.file.SensitivityWatchEventModifier;
import java.io.File;
import java.io.IOException;
import java.nio.file.ClosedWatchServiceException;
import java.nio.file.FileSystems;
import java.nio.file.StandardWatchEventKinds;
import java.nio.file.WatchEvent;
@ -41,6 +42,8 @@ public class PluginWatcherTask extends AbstractTask {
private File file;
private final AtomicBoolean run;
private WatchService watchService;
/**
* Constructs a new PluginWatcherTask for the specified plugin.
* @param pluginName The name of the plugin.
@ -55,6 +58,8 @@ public class PluginWatcherTask extends AbstractTask {
@Override
public void run() {
try (WatchService watchService = FileSystems.getDefault().newWatchService()) {
this.watchService = watchService;
File folder = pluginManager.getPluginsFolder();
folder.toPath().register(watchService, EVENTS, SensitivityWatchEventModifier.HIGH);
@ -76,9 +81,9 @@ public class PluginWatcherTask extends AbstractTask {
break;
}
}
} catch (IOException ex) {
} catch (IOException | InterruptedException ex) {
ex.printStackTrace();
} catch (InterruptedException ignored) {
} catch (ClosedWatchServiceException ignored) {
//
}
}
@ -93,5 +98,10 @@ public class PluginWatcherTask extends AbstractTask {
@Override
public void cancel() {
run.set(false);
try {
watchService.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}