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();
|
Class<? extends Event> eventType = event.getClass();
|
||||||
if (handlers.containsKey(eventType)) {
|
if (handlers.containsKey(eventType)) {
|
||||||
for (ExecutorLink link : handlers.get(eventType)) {
|
for (ExecutorLink link : handlers.get(eventType)) {
|
||||||
|
if (link.isIgnoreCancelled() && event.isCanceled())
|
||||||
|
continue;
|
||||||
try {
|
try {
|
||||||
link.getMethod().invoke(link.object, event);
|
link.getMethod().invoke(link.object, event);
|
||||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||||
|
|||||||
@@ -11,29 +11,47 @@ import java.lang.reflect.InvocationTargetException;
|
|||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.concurrent.CountDownLatch;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
@SuppressWarnings("Duplicates")
|
@SuppressWarnings("Duplicates")
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class AsyncEventLoop extends BaseEventLoop {
|
public class AsyncEventLoop extends BaseEventLoop {
|
||||||
private Map<Class<? extends Event>, List<ExecutorLink>> handlers = new HashMap<>();
|
private Map<Class<? extends Event>, List<ExecutorLink>> handlers = new HashMap<>();
|
||||||
|
private ExecutorService preEventExecutor = Executors.newSingleThreadExecutor();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void callEvent(Event event) {
|
public void callEvent(Event event) {
|
||||||
Class<? extends Event> eventType = event.getClass();
|
Class<? extends Event> eventType = event.getClass();
|
||||||
|
|
||||||
if (handlers.containsKey(eventType)) {
|
if (handlers.containsKey(eventType)) {
|
||||||
for (ExecutorLink link : handlers.get(eventType)) {
|
List<ExecutorLink> handlerList = handlers.get(eventType);
|
||||||
Object preprocessResult = null;
|
EventBatch eventBatch = new EventBatch(handlerList.size());
|
||||||
if (link.getPreprocessMethod() != null) {
|
CountDownLatch latch = new CountDownLatch(handlerList.size());
|
||||||
try {
|
|
||||||
preprocessResult = link.getPreprocessMethod().invoke(link.object, event);
|
for (int i = 0; i < handlerList.size(); i++) {
|
||||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
if (handlerList.get(i).getPreprocessMethod() == null) {
|
||||||
log.error("Exception caught while attempting to run event preprocessing for {}.", eventType.getSimpleName(), e);
|
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 {
|
try {
|
||||||
if (link.getResultInjection() != null)
|
if (link.getResultInjection() != null)
|
||||||
link.getMethod().invoke(link.object, event, preprocessResult);
|
link.getMethod().invoke(link.object, event, eventBatch.getInjectionObject(i));
|
||||||
else
|
else
|
||||||
link.getMethod().invoke(link.object, event);
|
link.getMethod().invoke(link.object, event);
|
||||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||||
@@ -130,7 +148,7 @@ public class AsyncEventLoop extends BaseEventLoop {
|
|||||||
*/
|
*/
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
@Getter
|
@Getter
|
||||||
private static class ExecutorLink {
|
static class ExecutorLink {
|
||||||
private final int priority;
|
private final int priority;
|
||||||
private final boolean ignoreCancelled;
|
private final boolean ignoreCancelled;
|
||||||
private final Method method;
|
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