Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add TaskFactory #68

Merged
merged 8 commits into from
Oct 4, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions api/src/main/java/net/okocraft/box/api/BoxAPI.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@
import net.okocraft.box.api.model.manager.StockManager;
import net.okocraft.box.api.model.manager.UserManager;
import net.okocraft.box.api.player.BoxPlayerMap;
import net.okocraft.box.api.taskfactory.TaskFactory;
import net.okocraft.box.api.util.ExecutorProvider;
import org.bukkit.NamespacedKey;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Unmodifiable;

Expand Down Expand Up @@ -106,11 +108,20 @@ public interface BoxAPI {
*/
@NotNull CustomDataContainer getCustomDataContainer();

/**
* Gets the {@link TaskFactory}.
*
* @return the {@link TaskFactory}
*/
@NotNull TaskFactory getTaskFactory();

/**
* Gets the {@link ExecutorProvider}.
*
* @return the {@link ExecutorProvider}
*/
@Deprecated(forRemoval = true)
@ApiStatus.ScheduledForRemoval(inVersion = "4.2.0")
@NotNull ExecutorProvider getExecutorProvider();

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package net.okocraft.box.api.taskfactory;

import org.jetbrains.annotations.NotNull;

import java.util.concurrent.CompletableFuture;
import java.util.function.Supplier;

/**
* An interface to create {@link CompletableFuture}s.
*/
public interface TaskFactory {

/**
* Creates a {@link CompletableFuture} to run the task on main thread.
*
* @param task the task to run
* @return the new {@link CompletableFuture}
*/
@NotNull CompletableFuture<Void> run(@NotNull Runnable task);

/**
* Creates a {@link CompletableFuture} to supply values on main thread.
*
* @param supplier the supplier
* @param <T> the value type
* @return the new {@link CompletableFuture}
*/
<T> @NotNull CompletableFuture<T> supply(@NotNull Supplier<T> supplier);

/**
* Creates a {@link CompletableFuture} to run the task asynchronously.
*
* @param task the task to run
* @return the new {@link CompletableFuture}
*/
@NotNull CompletableFuture<Void> runAsync(@NotNull Runnable task);

/**
* Creates a {@link CompletableFuture} to supply values asynchronously.
*
* @param supplier the supplier
* @param <T> the value type
* @return the new {@link CompletableFuture}
*/
<T> @NotNull CompletableFuture<T> supplyAsync(@NotNull Supplier<T> supplier);

}
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
package net.okocraft.box.api.util;

import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;

import java.util.concurrent.Executor;

/**
* An interface for providing {@link Executor}s.
*/
@Deprecated(forRemoval = true)
@ApiStatus.ScheduledForRemoval(inVersion = "4.2.0")
public interface ExecutorProvider {

/**
Expand Down
10 changes: 9 additions & 1 deletion core/src/main/java/net/okocraft/box/core/BoxPlugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import net.okocraft.box.api.model.manager.StockManager;
import net.okocraft.box.api.model.manager.UserManager;
import net.okocraft.box.api.player.BoxPlayerMap;
import net.okocraft.box.api.taskfactory.TaskFactory;
import net.okocraft.box.api.util.ExecutorProvider;
import net.okocraft.box.core.command.BoxAdminCommandImpl;
import net.okocraft.box.core.command.BoxCommandImpl;
Expand All @@ -35,6 +36,7 @@
import net.okocraft.box.core.storage.Storage;
import net.okocraft.box.core.storage.implementations.yaml.YamlStorage;
import net.okocraft.box.core.task.AutoSaveTask;
import net.okocraft.box.core.taskfactory.BoxTaskFactory;
import net.okocraft.box.core.util.executor.BoxExecutorProvider;
import net.okocraft.box.core.util.executor.InternalExecutors;
import org.bukkit.Bukkit;
Expand Down Expand Up @@ -70,6 +72,7 @@ public class BoxPlugin implements BoxAPI {
private final DebugListener debugListener = new DebugListener();

private final EventBus eventBus = EventBus.newEventBus();
private final BoxTaskFactory taskFactory = new BoxTaskFactory();
private final BoxExecutorProvider executorProvider = new BoxExecutorProvider();

private final BoxCommandImpl boxCommand = new BoxCommandImpl();
Expand Down Expand Up @@ -221,7 +224,7 @@ public void disable() {
getLogger().info("Shutting down executors...");

try {
executorProvider.shutdown();
taskFactory.shutdown();
InternalExecutors.shutdownAll();
} catch (InterruptedException e) {
getLogger().log(Level.SEVERE, "Could not shutdown executors", e);
Expand Down Expand Up @@ -339,6 +342,11 @@ private void saveDefaultLanguages(@NotNull Path directory) throws IOException {
return customDataContainer;
}

@Override
public @NotNull TaskFactory getTaskFactory() {
return taskFactory;
}

@Override
public @NotNull ExecutorProvider getExecutorProvider() {
return executorProvider;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.CompletableFuture;
import java.util.logging.Level;

import static net.kyori.adventure.text.Component.text;
Expand Down Expand Up @@ -171,10 +170,9 @@ private void sendHelp(@NotNull CommandSender sender) {
}

private void runCommandAsync(@NotNull Command command, @NotNull CommandSender sender, @NotNull String[] args) {
CompletableFuture.runAsync(
() -> command.onCommand(sender, args),
BoxProvider.get().getExecutorProvider().getExecutor()
).exceptionallyAsync(e -> reportError(sender, args, e));
BoxProvider.get().getTaskFactory()
.runAsync(() -> command.onCommand(sender, args))
.exceptionallyAsync(e -> reportError(sender, args, e));
}

private @Nullable Void reportError(@NotNull CommandSender sender, @NotNull String[] args, @NotNull Throwable throwable) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package net.okocraft.box.core.taskfactory;

import com.google.common.util.concurrent.ThreadFactoryBuilder;
import net.okocraft.box.api.BoxProvider;
import net.okocraft.box.api.taskfactory.TaskFactory;
import org.bukkit.Bukkit;
import org.jetbrains.annotations.NotNull;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;
import java.util.logging.Level;

public class BoxTaskFactory implements TaskFactory {

private final ExecutorService executor = Executors.newFixedThreadPool(
Math.min(Runtime.getRuntime().availableProcessors(), 4),
new ThreadFactoryBuilder()
.setDaemon(true)
.setNameFormat("box-worker-%d")
.setUncaughtExceptionHandler(this::reportUncaughtException)
.build()
);

@Override
public @NotNull CompletableFuture<Void> run(@NotNull Runnable task) {
return CompletableFuture.runAsync(task, getMainThread());
}

@Override
public @NotNull <T> CompletableFuture<T> supply(@NotNull Supplier<T> supplier) {
return CompletableFuture.supplyAsync(supplier, getMainThread());
}

@Override
public @NotNull CompletableFuture<Void> runAsync(@NotNull Runnable task) {
return CompletableFuture.runAsync(task, executor);
}

@Override
public @NotNull <T> CompletableFuture<T> supplyAsync(@NotNull Supplier<T> supplier) {
return CompletableFuture.supplyAsync(supplier, executor);
}

public void shutdown() throws InterruptedException {
executor.shutdown();

//noinspection ResultOfMethodCallIgnored
executor.awaitTermination(1, TimeUnit.MINUTES);
}

private void reportUncaughtException(@NotNull Thread thread, @NotNull Throwable throwable) {
BoxProvider.get().getLogger().log(
Level.SEVERE,
"An exception occurred in the thread " + thread.getName(),
throwable
);
}

public @NotNull Executor getExecutor() {
return executor;
}

public @NotNull Executor getMainThread() {
return Bukkit.getScheduler().getMainThreadExecutor(BoxProvider.get().getPluginInstance());
}
}
Original file line number Diff line number Diff line change
@@ -1,51 +1,21 @@
package net.okocraft.box.core.util.executor;

import com.google.common.util.concurrent.ThreadFactoryBuilder;
import net.okocraft.box.api.BoxProvider;
import net.okocraft.box.api.util.ExecutorProvider;
import org.bukkit.Bukkit;
import net.okocraft.box.core.taskfactory.BoxTaskFactory;
import org.jetbrains.annotations.NotNull;

import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;

public class BoxExecutorProvider implements ExecutorProvider {

private final ExecutorService executor = Executors.newFixedThreadPool(
Math.min(Runtime.getRuntime().availableProcessors(), 4),
new ThreadFactoryBuilder()
.setDaemon(true)
.setNameFormat("box-worker-%d")
.setUncaughtExceptionHandler(this::reportUncaughtException)
.build()
);

@Override
public @NotNull Executor getExecutor() {
return executor;
return ((BoxTaskFactory) BoxProvider.get().getTaskFactory()).getExecutor();
}

@Override
public @NotNull Executor getMainThread() {
return Bukkit.getScheduler().getMainThreadExecutor(BoxProvider.get().getPluginInstance());
}

public void shutdown() throws InterruptedException {
executor.shutdown();

//noinspection ResultOfMethodCallIgnored
executor.awaitTermination(1, TimeUnit.MINUTES);
}


private void reportUncaughtException(@NotNull Thread thread, @NotNull Throwable throwable) {
BoxProvider.get().getLogger().log(
Level.SEVERE,
"An exception occurred in the thread " + thread.getName(),
throwable
);
return ((BoxTaskFactory) BoxProvider.get().getTaskFactory()).getMainThread();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

Expand Down Expand Up @@ -97,10 +96,9 @@ public void onCommand(@NotNull CommandSender sender, @NotNull String[] args) {

private void depositItemInMainHand(@NotNull Player player, int amount) {
var result =
CompletableFuture.supplyAsync(
() -> InventoryTransaction.depositItemInMainHand(player, amount),
BoxProvider.get().getExecutorProvider().getMainThread()
).join();
BoxProvider.get().getTaskFactory()
.supply(() -> InventoryTransaction.depositItemInMainHand(player, amount))
.join();

if (result.getType().isModified()) {
var item = result.getItem();
Expand All @@ -122,10 +120,9 @@ private void depositItemInMainHand(@NotNull Player player, int amount) {

private void depositAll(@NotNull Player player) {
var resultList =
CompletableFuture.supplyAsync(
() -> InventoryTransaction.depositItemsInInventory(player.getInventory()),
BoxProvider.get().getExecutorProvider().getMainThread()
).join();
BoxProvider.get().getTaskFactory()
.supply(() -> InventoryTransaction.depositItemsInInventory(player.getInventory()))
.join();

var stockHolder = BoxProvider.get().getBoxPlayerMap().get(player).getCurrentStockHolder();

Expand All @@ -138,10 +135,9 @@ private void depositAll(@NotNull Player player) {

private void depositItem(@NotNull Player player, @NotNull BoxItem boxItem, int amount) {
var resultList =
CompletableFuture.supplyAsync(
() -> InventoryTransaction.depositItem(player.getInventory(), boxItem, amount),
BoxProvider.get().getExecutorProvider().getMainThread()
).join();
BoxProvider.get().getTaskFactory()
.supply(() -> InventoryTransaction.depositItem(player.getInventory(), boxItem, amount))
.join();

var stockHolder = BoxProvider.get().getBoxPlayerMap().get(player).getCurrentStockHolder();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

public class WithdrawCommand extends AbstractCommand {
Expand Down Expand Up @@ -70,10 +69,9 @@ public void onCommand(@NotNull CommandSender sender, @NotNull String[] args) {
}

var result =
CompletableFuture.supplyAsync(
() -> InventoryTransaction.withdraw(player.getInventory(), boxItem, amount),
BoxProvider.get().getExecutorProvider().getMainThread()
).join();
BoxProvider.get().getTaskFactory()
.supply(() -> InventoryTransaction.withdraw(player.getInventory(), boxItem, amount))
.join();

var resultType = result.getType();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
import org.jetbrains.annotations.NotNull;

import java.util.HashMap;
import java.util.concurrent.CompletableFuture;

public class ItemCrafter {

Expand Down Expand Up @@ -52,13 +51,10 @@ public static boolean craft(@NotNull Player crafter, @NotNull SelectedRecipe rec
int storeAmount = resultAmount;

if (Distribution.toInventory(crafter)) {
var result = CompletableFuture.supplyAsync(
() -> InventoryTransaction.withdraw(
crafter.getInventory(),
recipe.result(),
resultAmount
), BoxProvider.get().getExecutorProvider().getMainThread()
).join();
var result =
BoxProvider.get().getTaskFactory().supply(
() -> InventoryTransaction.withdraw(crafter.getInventory(), recipe.result(), resultAmount)
).join();

if (result.getType().isModified()) {
storeAmount = resultAmount - result.getAmount();
Expand Down
Loading