Archived
0

Implemented proper Async Event Loop

This commit is contained in:
Daniil
2018-07-25 23:17:14 +07:00
parent 8fef284019
commit 0ab539d4ef
4 changed files with 79 additions and 10 deletions

View File

@@ -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) {

View File

@@ -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;

View File

@@ -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;
}
}

View File

@@ -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();
}
}
}