304 lines
9.7 KiB
Java
304 lines
9.7 KiB
Java
/*
|
|
* PlotSquared, a land and world management plugin for Minecraft.
|
|
* Copyright (C) IntellectualSites <https://intellectualsites.com>
|
|
* Copyright (C) IntellectualSites team and contributors
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
package com.plotsquared.core.util.task;
|
|
|
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
|
|
|
import java.util.Collection;
|
|
import java.util.HashMap;
|
|
import java.util.HashSet;
|
|
import java.util.Iterator;
|
|
import java.util.Map;
|
|
import java.util.Set;
|
|
import java.util.concurrent.Callable;
|
|
import java.util.concurrent.CompletableFuture;
|
|
import java.util.concurrent.Future;
|
|
import java.util.concurrent.atomic.AtomicInteger;
|
|
|
|
/**
|
|
* Task manager that handles scheduling of tasks.
|
|
* Synchronous methods make no guarantee of being scheduled on the
|
|
* server thread, instead they guarantee that no two synchronous
|
|
* operations happen at the same time. Implementations of
|
|
* the task manager might make other guarantees. All asynchronous
|
|
* operations will happen on another thread, no matter where
|
|
* they're scheduled from.
|
|
*/
|
|
public abstract class TaskManager {
|
|
|
|
private static final Set<String> teleportQueue = new HashSet<>();
|
|
private static final Map<Integer, PlotSquaredTask> tasks = new HashMap<>();
|
|
public static AtomicInteger index = new AtomicInteger(0);
|
|
|
|
private static TaskManager platformImplementation;
|
|
|
|
/**
|
|
* Add a string to the teleport queue
|
|
*
|
|
* @param string String to add
|
|
*/
|
|
public static void addToTeleportQueue(final @NonNull String string) {
|
|
teleportQueue.add(string);
|
|
}
|
|
|
|
/**
|
|
* Remove a string from the teleport queue
|
|
*
|
|
* @param string String to remove
|
|
* return {@code true} if the value was stored in the map, or {@code false}
|
|
* @return if string was actually removed
|
|
*/
|
|
public static boolean removeFromTeleportQueue(final @NonNull String string) {
|
|
return teleportQueue.remove(string);
|
|
}
|
|
|
|
/**
|
|
* Add a task to the task map
|
|
*
|
|
* @param task Task
|
|
* @param id Task ID
|
|
*/
|
|
public static void addTask(final @NonNull PlotSquaredTask task, final int id) {
|
|
tasks.put(id, task);
|
|
}
|
|
|
|
/**
|
|
* Remove a task from the task map and return the stored value
|
|
*
|
|
* @param id Task ID
|
|
* @return Task if stored, or {@code null}
|
|
*/
|
|
public static @Nullable PlotSquaredTask removeTask(final int id) {
|
|
return tasks.remove(id);
|
|
}
|
|
|
|
/**
|
|
* Run a repeating synchronous task. If using a platform scheduler,
|
|
* this is guaranteed to run on the server thread
|
|
*
|
|
* @param runnable Task to run
|
|
* @param taskTime Task interval
|
|
* @return Created task object, can be used to cancel the task
|
|
*/
|
|
public static @NonNull PlotSquaredTask runTaskRepeat(
|
|
final @Nullable Runnable runnable,
|
|
final @NonNull TaskTime taskTime
|
|
) {
|
|
if (runnable != null) {
|
|
if (getPlatformImplementation() == null) {
|
|
throw new IllegalArgumentException("disabled");
|
|
}
|
|
return getPlatformImplementation().taskRepeat(runnable, taskTime);
|
|
}
|
|
return PlotSquaredTask.nullTask();
|
|
}
|
|
|
|
/**
|
|
* Run an asynchronous task. This will never run on the server thread
|
|
*
|
|
* @param runnable Task to run
|
|
*/
|
|
public static void runTaskAsync(final @Nullable Runnable runnable) {
|
|
if (runnable != null) {
|
|
if (getPlatformImplementation() == null) {
|
|
runnable.run();
|
|
return;
|
|
}
|
|
getPlatformImplementation().taskAsync(runnable);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Run a synchronous task. If using a platform scheduler, this is guaranteed
|
|
* to run on the server thread
|
|
*
|
|
* @param runnable Task to run
|
|
*/
|
|
public static void runTask(final @Nullable Runnable runnable) {
|
|
if (runnable != null) {
|
|
if (getPlatformImplementation() == null) {
|
|
runnable.run();
|
|
return;
|
|
}
|
|
getPlatformImplementation().task(runnable);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Run a synchronous task after a given delay.
|
|
* If using a platform scheduler, this is guaranteed to run on the server thread
|
|
*
|
|
* @param runnable Task to run
|
|
* @param taskTime Task delay
|
|
*/
|
|
public static void runTaskLater(
|
|
final @Nullable Runnable runnable,
|
|
final @NonNull TaskTime taskTime
|
|
) {
|
|
if (runnable != null) {
|
|
if (getPlatformImplementation() == null) {
|
|
runnable.run();
|
|
return;
|
|
}
|
|
getPlatformImplementation().taskLater(runnable, taskTime);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Run an asynchronous task after a given delay. This will never
|
|
* run on the server thread
|
|
*
|
|
* @param runnable Task to run
|
|
* @param taskTime Task delay
|
|
*/
|
|
public static void runTaskLaterAsync(
|
|
final @Nullable Runnable runnable,
|
|
final @NonNull TaskTime taskTime
|
|
) {
|
|
if (runnable != null) {
|
|
if (getPlatformImplementation() == null) {
|
|
runnable.run();
|
|
return;
|
|
}
|
|
getPlatformImplementation().taskLaterAsync(runnable, taskTime);
|
|
}
|
|
}
|
|
|
|
public static @Nullable TaskManager getPlatformImplementation() {
|
|
return platformImplementation;
|
|
}
|
|
|
|
public static void setPlatformImplementation(final @NonNull TaskManager implementation) {
|
|
platformImplementation = implementation;
|
|
}
|
|
|
|
/**
|
|
* Break up a series of tasks so that they can run without lagging the server
|
|
*
|
|
* @param objects Objects to perform the task on
|
|
* @param task Task to perform
|
|
* @param <T> Object type
|
|
* @return Future that completes when the tasks are done
|
|
*/
|
|
public <T> CompletableFuture<Void> objectTask(
|
|
final @NonNull Collection<T> objects,
|
|
final @NonNull RunnableVal<T> task
|
|
) {
|
|
final Iterator<T> iterator = objects.iterator();
|
|
final ObjectTaskRunnable<T> taskRunnable = new ObjectTaskRunnable<>(iterator, task);
|
|
TaskManager.runTask(taskRunnable);
|
|
return taskRunnable.getCompletionFuture();
|
|
}
|
|
|
|
/**
|
|
* Make a synchronous method call and return the result
|
|
*
|
|
* @param function Method to call
|
|
* @param <T> Return type
|
|
* @return Method result
|
|
* @throws Exception If the call fails
|
|
*/
|
|
public <T> T sync(final @NonNull Callable<T> function) throws Exception {
|
|
return sync(function, Integer.MAX_VALUE);
|
|
}
|
|
|
|
/**
|
|
* Make a synchronous method call and return the result
|
|
*
|
|
* @param function Method to call
|
|
* @param timeout Timeout (ms)
|
|
* @param <T> Return type
|
|
* @return Method result
|
|
* @throws Exception If the call fails
|
|
*/
|
|
public abstract <T> T sync(final @NonNull Callable<T> function, final int timeout)
|
|
throws Exception;
|
|
|
|
/**
|
|
* Call a method synchronously and return a future with
|
|
* the result of the result
|
|
*
|
|
* @param method Method to be ran synchronously
|
|
* @param <T> Return type
|
|
* @return Future completing with the result
|
|
*/
|
|
public abstract <T> Future<T> callMethodSync(final @NonNull Callable<T> method);
|
|
|
|
/**
|
|
* Run a repeating synchronous task. If using a platform scheduler,
|
|
* this is guaranteed to run on the server thread
|
|
*
|
|
* @param runnable Task to run
|
|
* @param taskTime Task interval
|
|
* @return Created task object, can be used to cancel the task
|
|
*/
|
|
public abstract PlotSquaredTask taskRepeat(
|
|
@NonNull Runnable runnable,
|
|
@NonNull TaskTime taskTime
|
|
);
|
|
|
|
/**
|
|
* Run a repeating asynchronous task. This will never run on the
|
|
* server thread
|
|
*
|
|
* @param runnable Task to run
|
|
* @param taskTime Task interval
|
|
* @return Created task object, can be used to cancel the task
|
|
*/
|
|
public abstract PlotSquaredTask taskRepeatAsync(
|
|
@NonNull Runnable runnable,
|
|
@NonNull TaskTime taskTime
|
|
);
|
|
|
|
/**
|
|
* Run an asynchronous task. This will never run on the server thread
|
|
*
|
|
* @param runnable Task to run
|
|
*/
|
|
public abstract void taskAsync(@NonNull Runnable runnable);
|
|
|
|
/**
|
|
* Run a synchronous task. If using a platform scheduler, this is guaranteed
|
|
* to run on the server thread
|
|
*
|
|
* @param runnable Task to run
|
|
*/
|
|
public abstract void task(@NonNull Runnable runnable);
|
|
|
|
/**
|
|
* Run a synchronous task after a given delay.
|
|
* If using a platform scheduler, this is guaranteed to run on the server thread
|
|
*
|
|
* @param runnable Task to run
|
|
* @param taskTime Task delay
|
|
*/
|
|
public abstract void taskLater(@NonNull Runnable runnable, @NonNull TaskTime taskTime);
|
|
|
|
/**
|
|
* Run an asynchronous task after a given delay. This will never
|
|
* run on the server thread
|
|
*
|
|
* @param runnable Task to run
|
|
* @param taskTime Task delay
|
|
*/
|
|
public abstract void taskLaterAsync(@NonNull Runnable runnable, @NonNull TaskTime taskTime);
|
|
|
|
}
|