From f8a6fbd7197a44b0dc8752d1fe8fda438373db81 Mon Sep 17 00:00:00 2001 From: Ashcon Partovi Date: Thu, 16 Apr 2020 09:38:18 -0700 Subject: [PATCH] Execute commands on the same thread they were submitted on * This fixes an issue where Bukkit commands would unexpectedly run off the main thread Signed-off-by: Ashcon Partovi --- .../parametric/CommandExecutorWrapper.java | 34 +++++++++++++++---- .../intake/parametric/ParametricBuilder.java | 4 +-- 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/core/src/main/java/app/ashcon/intake/parametric/CommandExecutorWrapper.java b/core/src/main/java/app/ashcon/intake/parametric/CommandExecutorWrapper.java index 8e78073..723538d 100644 --- a/core/src/main/java/app/ashcon/intake/parametric/CommandExecutorWrapper.java +++ b/core/src/main/java/app/ashcon/intake/parametric/CommandExecutorWrapper.java @@ -22,21 +22,41 @@ import app.ashcon.intake.argument.CommandArgs; import java.util.concurrent.Callable; -import java.util.concurrent.ExecutorService; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executor; import java.util.concurrent.Future; /** Wraps an ExecutorService into a CommandExecutor. */ public class CommandExecutorWrapper implements CommandExecutor { - private final ExecutorService executorService; + private final Executor executor; - public CommandExecutorWrapper(ExecutorService executorService) { - checkNotNull(executorService, "executorService"); - this.executorService = executorService; + public CommandExecutorWrapper(Executor executor) { + checkNotNull(executor, "executor"); + this.executor = executor; } @Override - public Future submit(Callable task, CommandArgs args) { - return executorService.submit(task); + public Future submit(Callable callable, CommandArgs args) { + Task task = new Task<>(callable); + executor.execute(task); + return task; + } + + private static class Task extends CompletableFuture implements Runnable { + private final Callable task; + + private Task(Callable task) { + this.task = checkNotNull(task, "task"); + } + + @Override + public void run() { + try { + complete(task.call()); + } catch (Throwable t) { + completeExceptionally(t); + } + } } } diff --git a/core/src/main/java/app/ashcon/intake/parametric/ParametricBuilder.java b/core/src/main/java/app/ashcon/intake/parametric/ParametricBuilder.java index 6a7f645..ac07030 100644 --- a/core/src/main/java/app/ashcon/intake/parametric/ParametricBuilder.java +++ b/core/src/main/java/app/ashcon/intake/parametric/ParametricBuilder.java @@ -35,7 +35,6 @@ import java.lang.reflect.Method; import java.util.List; import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; /** * Keeps a mapping of types to bindings and generates commands from classes with appropriate @@ -49,7 +48,8 @@ public class ParametricBuilder { private Authorizer authorizer = new NullAuthorizer(); private CommandCompleter defaultCompleter = new NullCompleter(); private CommandExecutor commandExecutor = - new CommandExecutorWrapper(Executors.newSingleThreadExecutor()); + new CommandExecutorWrapper( + Runnable::run); // Runs commands on the same thread they were submitted on public ParametricBuilder(Injector injector) { this.injector = injector;