Compare commits

...

2 Commits

Author SHA1 Message Date
e9c97df089 Fix issue avoiding the mod not to compile, add a test for asyncTasks (still need to be implemented)
Signed-off-by: Quentin Legot <legotquentin@gmail.com>
2023-02-03 23:52:50 +01:00
e7178d44a9 PeriodicSyncTask and AsyncPeriodicTasks should work now (untested)
Signed-off-by: Quentin Legot <legotquentin@gmail.com>
2023-02-03 23:40:01 +01:00
14 changed files with 126 additions and 81 deletions

View File

@ -5,7 +5,7 @@ public abstract class AltarikRunnable implements Runnable {
private boolean isCancelled = false; private boolean isCancelled = false;
/** /**
* Warning: Some task cannot be cancelled (mostly async tasks like {@link fr.altarik.toolbox.task.asyncTasks.AsyncTasks} * Warning: Some task cannot be cancelled (mostly async tasks like {@link fr.altarik.toolbox.task.async.AsyncTasks}
* The result of this call is ignored in this case, you can still add a way to not execute its content (like if(isCancelled) return;) * The result of this call is ignored in this case, you can still add a way to not execute its content (like if(isCancelled) return;)
*/ */
public void cancel() { public void cancel() {

View File

@ -1,4 +0,0 @@
package fr.altarik.toolbox.task;
public interface AsyncTaskI extends TaskI, AutoCloseable {
}

View File

@ -8,7 +8,7 @@ public interface PeriodicTaskI extends TaskI {
* @param delay delay before starting the task * @param delay delay before starting the task
* @param period time to wait between runs * @param period time to wait between runs
* @throws InterruptedException When executed asynchronously, task may be interrupted * @throws InterruptedException When executed asynchronously, task may be interrupted
* @see fr.altarik.toolbox.task.syncTasks.PeriodicSyncTask * @see fr.altarik.toolbox.task.sync.PeriodicSyncTask
*/ */
public void addTask(AltarikRunnable function, long delay, long period) throws InterruptedException; public void addTask(AltarikRunnable function, long delay, long period) throws InterruptedException;
} }

View File

@ -1,15 +1,29 @@
package fr.altarik.toolbox.task.syncTasks; package fr.altarik.toolbox.task;
import fr.altarik.toolbox.task.AltarikRunnable;
public class SchedulerTaskData { public class SchedulerTaskData {
/**
* Delay before executing the function for the first time
* Correspond to tick in synchronous context and milliseconds in asynchronous context
*/
private final long delay; private final long delay;
/**
* Period of time before re-executing the function
* Correspond to tick in synchronous context and milliseconds in asynchronous context
*/
private final long period; private final long period;
private final AltarikRunnable function; private final AltarikRunnable function;
private long currentDelay; private long currentDelay;
/**
*
* Delay and Period times corresponds to tick in synchronous context and milliseconds in asynchronous context
*
* @param function instructions to execute
* @param delay Delay before executing the function for the first time
* @param period Period of time before re-executing the function
*/
public SchedulerTaskData(AltarikRunnable function, long delay, long period) { public SchedulerTaskData(AltarikRunnable function, long delay, long period) {
this.function = function; this.function = function;
this.delay = delay; this.delay = delay;
@ -36,4 +50,6 @@ public class SchedulerTaskData {
public long getPeriod() { public long getPeriod() {
return period; return period;
} }
} }

View File

@ -1,6 +1,6 @@
package fr.altarik.toolbox.task; package fr.altarik.toolbox.task;
import fr.altarik.toolbox.task.asyncTasks.AsyncTasks; import fr.altarik.toolbox.task.async.AsyncTasks;
import net.fabricmc.api.ModInitializer; import net.fabricmc.api.ModInitializer;
public class Task implements ModInitializer { public class Task implements ModInitializer {

View File

@ -1,6 +1,8 @@
package fr.altarik.toolbox.task.asyncTasks; package fr.altarik.toolbox.task.async;
import fr.altarik.toolbox.task.*; import fr.altarik.toolbox.task.AltarikRunnable;
import fr.altarik.toolbox.task.PeriodicTaskI;
import fr.altarik.toolbox.task.TaskI;
import it.unimi.dsi.fastutil.ints.IntComparators; import it.unimi.dsi.fastutil.ints.IntComparators;
import java.util.ArrayList; import java.util.ArrayList;
@ -56,7 +58,7 @@ public class AsyncPeriodicTasks implements PeriodicTaskI, AsyncTaskI {
@Override @Override
public void addTask(AltarikRunnable function) throws InterruptedException { public void addTask(AltarikRunnable function) throws InterruptedException {
this.addTask(function, 0, 1); this.addTask(function, 0, 1000);
} }
@Override @Override

View File

@ -0,0 +1,6 @@
package fr.altarik.toolbox.task.async;
import fr.altarik.toolbox.task.TaskI;
public interface AsyncTaskI extends TaskI, AutoCloseable {
}

View File

@ -1,7 +1,6 @@
package fr.altarik.toolbox.task.asyncTasks; package fr.altarik.toolbox.task.async;
import fr.altarik.toolbox.task.AltarikRunnable; import fr.altarik.toolbox.task.AltarikRunnable;
import fr.altarik.toolbox.task.TaskI;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
@ -10,7 +9,7 @@ import java.util.concurrent.TimeUnit;
/** /**
* A non-blocking small sized time-consuming tasks to executed asynchronously. * A non-blocking small sized time-consuming tasks to executed asynchronously.
*/ */
public class AsyncTasks implements TaskI { public class AsyncTasks implements AsyncTaskI {
private final ExecutorService worker; private final ExecutorService worker;
@ -30,11 +29,11 @@ public class AsyncTasks implements TaskI {
* *
* @return an instance of AsyncTasks * @return an instance of AsyncTasks
*/ */
public static TaskI initialize(int numberOfWorker) { public static AsyncTaskI initialize(int numberOfWorker) {
return new AsyncTasks(numberOfWorker); return new AsyncTasks(numberOfWorker);
} }
public static TaskI initialize() { public static AsyncTaskI initialize() {
return initialize(Runtime.getRuntime().availableProcessors()); return initialize(Runtime.getRuntime().availableProcessors());
} }

View File

@ -1,16 +1,27 @@
package fr.altarik.toolbox.task; package fr.altarik.toolbox.task.async;
import fr.altarik.toolbox.task.syncTasks.SchedulerTaskData; import fr.altarik.toolbox.task.AltarikRunnable;
import fr.altarik.toolbox.task.SchedulerTaskData;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.HashMap;
import java.util.Vector; import java.util.Vector;
public class TaskScheduler { public class TaskScheduler {
private Vector<SchedulerTaskData> asyncTasks; private Vector<SchedulerTaskData> asyncTasks;
/**
* Return last time the method was executed, Value initialized to now when using sending the task to scheduler
*/
private HashMap<SchedulerTaskData, Instant> lastTimeExecution;
private boolean stop = false; private boolean stop = false;
public synchronized void sendAsyncTask(AltarikRunnable function, long delay, long period) throws InterruptedException { public synchronized void sendAsyncTask(AltarikRunnable function, long delay, long period) throws InterruptedException {
asyncTasks.addElement(new SchedulerTaskData(function, delay, period)); SchedulerTaskData data = new SchedulerTaskData(function, delay, period);
asyncTasks.addElement(data);
lastTimeExecution.put(new SchedulerTaskData(function, delay, period), Instant.now());
notify(); notify();
} }
@ -30,12 +41,13 @@ public class TaskScheduler {
asyncTasks.remove(data); asyncTasks.remove(data);
if(!data.getFunction().isCancelled()) { if(!data.getFunction().isCancelled()) {
long currentDelay = data.getCurrentDelay(); long currentDelay = data.getCurrentDelay();
if(currentDelay != 0) { Instant currentTime = Instant.now();
data.setCurrentDelay(currentDelay - 1); Instant lastExecution = lastTimeExecution.get(data);
asyncTasks.addElement(data); // (lastExec + delay) - currentTime
} else { if(lastExecution.plus(currentDelay, ChronoUnit.MILLIS).isBefore(currentTime)) {
data.getFunction().run(); data.getFunction().run();
data.setCurrentDelay(data.getPeriod()); data.setCurrentDelay(data.getPeriod());
lastTimeExecution.put(data, Instant.now());
asyncTasks.addElement(data); asyncTasks.addElement(data);
} }
} }

View File

@ -0,0 +1,57 @@
package fr.altarik.toolbox.task.sync;
import fr.altarik.toolbox.task.AltarikRunnable;
import fr.altarik.toolbox.task.PeriodicTaskI;
import fr.altarik.toolbox.task.SchedulerTaskData;
import fr.altarik.toolbox.task.TaskI;
import java.util.ArrayList;
import java.util.List;
public class PeriodicSyncTask implements PeriodicTaskI, Runnable {
private ServerTickListener listener;
private List<SchedulerTaskData> tasks;
private PeriodicSyncTask() {
this.listener = new ServerTickListener(this);
this.tasks = new ArrayList<>(2);
}
public static TaskI initialize() {
return new PeriodicSyncTask();
}
@Override
public void addTask(AltarikRunnable function) throws InterruptedException {
addTask(function, 0, 1);
}
@Override
public void run() {
List<SchedulerTaskData> removeList = new ArrayList<>(tasks.size());
for(SchedulerTaskData data : tasks) {
if(!data.getFunction().isCancelled()) {
long currentDelay = data.getCurrentDelay();
if(currentDelay != 0) {
data.setCurrentDelay(currentDelay - 1);
} else {
data.getFunction().run();
data.setCurrentDelay(data.getPeriod());
}
} else {
removeList.add(data);
}
}
for(SchedulerTaskData toRemove : removeList) {
tasks.remove(toRemove);
}
}
@Override
public void addTask(AltarikRunnable function, long delay, long period) throws InterruptedException {
tasks.add(new SchedulerTaskData(function, delay, period));
}
}

View File

@ -1,4 +1,4 @@
package fr.altarik.toolbox.task.syncTasks; package fr.altarik.toolbox.task.sync;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
@ -13,7 +13,7 @@ public class ServerTickListener {
} }
private void onServerTick(MinecraftServer minecraftServer) { private void onServerTick(MinecraftServer minecraftServer) {
task.run();
} }
} }

View File

@ -1,48 +0,0 @@
package fr.altarik.toolbox.task.syncTasks;
import fr.altarik.toolbox.task.AltarikRunnable;
import fr.altarik.toolbox.task.PeriodicTaskI;
import fr.altarik.toolbox.task.TaskI;
import java.util.ArrayList;
import java.util.List;
public class PeriodicSyncTask implements PeriodicTaskI, Runnable {
private ServerTickListener listener;
private List<AltarikRunnable> tasks;
private PeriodicSyncTask() {
this.listener = new ServerTickListener(this);
this.tasks = new ArrayList<>(2);
}
public static TaskI initialize() {
return new PeriodicSyncTask();
}
@Override
public void addTask(AltarikRunnable function) throws InterruptedException {
tasks.add(function);
}
@Override
public void run() {
List<AltarikRunnable> removeList = new ArrayList<>(tasks.size());
for(AltarikRunnable task : tasks) {
if(task.isCancelled()) {
removeList.add(task);
} else {
task.run();
}
}
tasks.removeAll(removeList);
}
@Override
public void addTask(AltarikRunnable function, long delay, long period) throws InterruptedException {
}
}

View File

@ -1,8 +1,7 @@
package fr.altarik.toolbox; package fr.altarik.toolbox.task;
import fr.altarik.toolbox.task.AltarikRunnable; import fr.altarik.toolbox.task.async.AsyncTaskI;
import fr.altarik.toolbox.task.TaskI; import fr.altarik.toolbox.task.async.AsyncTasks;
import fr.altarik.toolbox.task.asyncTasks.AsyncTasks;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import java.util.Date; import java.util.Date;
@ -21,7 +20,7 @@ class AsyncTaskTest {
void testAsyncOp() throws Exception { void testAsyncOp() throws Exception {
int numberOfTasks = 10000; int numberOfTasks = 10000;
System.out.println("Initializing async tasks worker"); System.out.println("Initializing async tasks worker");
TaskI worker = AsyncTasks.initialize(1); // only testing on a single worker, otherwise result have a high chance to not be in the order we want AsyncTaskI worker = AsyncTasks.initialize(1); // only testing on a single worker, otherwise result have a high chance to not be in the order we want
Stack<Integer> results = new Stack<>(); Stack<Integer> results = new Stack<>();
for(int i = 0; i < numberOfTasks; i++) { for(int i = 0; i < numberOfTasks; i++) {
System.out.println(log("sending task " + i)); System.out.println(log("sending task " + i));
@ -40,6 +39,5 @@ class AsyncTaskTest {
expected[i] = i; expected[i] = i;
} }
assertArrayEquals(expected, results.toArray()); assertArrayEquals(expected, results.toArray());
} }
} }

View File

@ -0,0 +1,7 @@
package fr.altarik.toolbox.task;
public class SyncTaskTest {
// TODO: 03/02/2023 Envoyé les tasks au workers grâce à un autre thread.
}