Implemented proper Async Event Loop
This commit is contained in:
@@ -17,6 +17,8 @@ public class SimpleEventLoop extends BaseEventLoop {
|
||||
Class<? extends Event> eventType = event.getClass();
|
||||
if (handlers.containsKey(eventType)) {
|
||||
for (ExecutorLink link : handlers.get(eventType)) {
|
||||
if (link.isIgnoreCancelled() && event.isCanceled())
|
||||
continue;
|
||||
try {
|
||||
link.getMethod().invoke(link.object, event);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
|
||||
@@ -11,29 +11,47 @@ import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
@SuppressWarnings("Duplicates")
|
||||
@Slf4j
|
||||
public class AsyncEventLoop extends BaseEventLoop {
|
||||
private Map<Class<? extends Event>, List<ExecutorLink>> handlers = new HashMap<>();
|
||||
private ExecutorService preEventExecutor = Executors.newSingleThreadExecutor();
|
||||
|
||||
@Override
|
||||
public void callEvent(Event event) {
|
||||
Class<? extends Event> eventType = event.getClass();
|
||||
|
||||
if (handlers.containsKey(eventType)) {
|
||||
for (ExecutorLink link : handlers.get(eventType)) {
|
||||
Object preprocessResult = null;
|
||||
if (link.getPreprocessMethod() != null) {
|
||||
try {
|
||||
preprocessResult = link.getPreprocessMethod().invoke(link.object, event);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
log.error("Exception caught while attempting to run event preprocessing for {}.", eventType.getSimpleName(), e);
|
||||
List<ExecutorLink> handlerList = handlers.get(eventType);
|
||||
EventBatch eventBatch = new EventBatch(handlerList.size());
|
||||
CountDownLatch latch = new CountDownLatch(handlerList.size());
|
||||
|
||||
for (int i = 0; i < handlerList.size(); i++) {
|
||||
if (handlerList.get(i).getPreprocessMethod() == null) {
|
||||
latch.countDown();
|
||||
continue;
|
||||
}
|
||||
preEventExecutor.submit(new PreprocessTask(i, eventBatch, latch, handlerList.get(i), event));
|
||||
}
|
||||
|
||||
try {
|
||||
latch.await();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
for (int i = 0; i < handlerList.size(); i++) {
|
||||
ExecutorLink link = handlerList.get(i);
|
||||
if (link.isIgnoreCancelled() && event.isCanceled())
|
||||
continue;
|
||||
|
||||
try {
|
||||
if (link.getResultInjection() != null)
|
||||
link.getMethod().invoke(link.object, event, preprocessResult);
|
||||
link.getMethod().invoke(link.object, event, eventBatch.getInjectionObject(i));
|
||||
else
|
||||
link.getMethod().invoke(link.object, event);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
@@ -130,7 +148,7 @@ public class AsyncEventLoop extends BaseEventLoop {
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Getter
|
||||
private static class ExecutorLink {
|
||||
static class ExecutorLink {
|
||||
private final int priority;
|
||||
private final boolean ignoreCancelled;
|
||||
private final Method method;
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
package mc.core.events.async;
|
||||
|
||||
public class EventBatch {
|
||||
private Object[] returnInject;
|
||||
|
||||
public EventBatch(int size) {
|
||||
this.returnInject = new Object[size];
|
||||
}
|
||||
|
||||
public Object getInjectionObject(int id) {
|
||||
return returnInject[id];
|
||||
}
|
||||
|
||||
public void setInjectionObject(int id, Object value) {
|
||||
returnInject[id] = value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package mc.core.events.async;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import mc.core.events.Event;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
public class PreprocessTask implements Runnable {
|
||||
private final int id;
|
||||
private final EventBatch eventBatch;
|
||||
private final CountDownLatch latch;
|
||||
private final AsyncEventLoop.ExecutorLink link;
|
||||
private final Event event;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
Object result = link.getPreprocessMethod().invoke(link.getObject(), event);
|
||||
if (result != null)
|
||||
eventBatch.setInjectionObject(id, result);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
log.error("Exception caught while attempting to run event preprocessing.", e);
|
||||
} finally {
|
||||
latch.countDown();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user