Splitting AdvancedEventLoop and AsyncEventLoop for the sake of comparision
This commit is contained in:
@@ -0,0 +1,145 @@
|
||||
package mc.core.events.async;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import mc.core.events.BaseEventLoop;
|
||||
import mc.core.events.Event;
|
||||
import mc.core.events.EventHandler;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.*;
|
||||
|
||||
@SuppressWarnings("Duplicates")
|
||||
@Slf4j
|
||||
public class AdvancedEventLoop extends BaseEventLoop {
|
||||
Map<Class<? extends Event>, List<ExecutorLink>> handlers = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public void callEvent(Event event) {
|
||||
Class<? extends Event> eventType = event.getClass();
|
||||
if (handlers.containsKey(eventType)) {
|
||||
for (ExecutorLink link : handlers.get(eventType)) {
|
||||
if (link.isIgnoreCancelled() && event.isCanceled())
|
||||
continue;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
if (link.getResultInjection() != null)
|
||||
link.getMethod().invoke(link.object, event, preprocessResult);
|
||||
else
|
||||
link.getMethod().invoke(link.object, event);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
log.error("Exception caught while attempting to dispatch {}.", eventType.getSimpleName(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addEventHandler(Object object) {
|
||||
Map<String, Method> preprocessors = new HashMap<>();
|
||||
|
||||
for (Method method : object.getClass().getDeclaredMethods()) {
|
||||
EventPreprocessor annotation = method.getAnnotation(EventPreprocessor.class);
|
||||
if (annotation == null)
|
||||
continue;
|
||||
|
||||
if (!Modifier.isPublic(method.getModifiers())) {
|
||||
log.error("Unable to register {} as an EventPreprocessor. Method must have a 'private' access modifier.", method.toString());
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
if (method.getParameterCount() != 1) {
|
||||
log.error("Unable to register {} as an EventPreprocessor. Method must have exactly one argument.", method.toString());
|
||||
continue;
|
||||
}
|
||||
|
||||
Class<?> firstParamType = method.getParameterTypes()[0];
|
||||
if (!Event.class.isAssignableFrom(firstParamType)) {
|
||||
log.error("Unable to register {} as an EventPreprocessor. First parameter type must implement 'Event' interface.", method.toString());
|
||||
continue;
|
||||
}
|
||||
|
||||
if (preprocessors.containsKey(annotation.methodName()))
|
||||
log.warn("Attempted to register multiple EventPreprocessors for the event {}. Please note, that only the last one will be registered.", annotation.methodName());
|
||||
preprocessors.put(annotation.methodName() + ":" + firstParamType.getSimpleName(), method);
|
||||
}
|
||||
|
||||
|
||||
for (Method method : object.getClass().getDeclaredMethods()) {
|
||||
EventHandler annotation = method.getAnnotation(EventHandler.class);
|
||||
|
||||
if (annotation == null)
|
||||
continue;
|
||||
|
||||
if (!Modifier.isPublic(method.getModifiers())) {
|
||||
log.error("Unable to register {} as an EventHandler. Method must have a 'private' access modifier.", method.toString());
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
if (method.getParameterCount() == 0) {
|
||||
log.error("Unable to register {} as an EventHandler. Method must at least one argument.", method.toString());
|
||||
continue;
|
||||
}
|
||||
|
||||
Class<?> firstParamType = method.getParameterTypes()[0];
|
||||
if (!Event.class.isAssignableFrom(firstParamType)) {
|
||||
log.error("Unable to register {} as an EventHandler. First parameter type must implement 'Event' interface.", method.toString());
|
||||
continue;
|
||||
}
|
||||
@SuppressWarnings("unchecked") Class<? extends Event> eventType = (Class<? extends Event>) method.getParameterTypes()[0];
|
||||
|
||||
Method preprocessMethod = preprocessors.get(method.getName() + ":" + eventType.getSimpleName());
|
||||
Class resultInjection = null;
|
||||
if (preprocessMethod.getReturnType() != void.class && method.getParameterCount() == 2 && preprocessMethod.getReturnType().equals(method.getParameterTypes()[1]))
|
||||
resultInjection = preprocessMethod.getReturnType();
|
||||
|
||||
if (resultInjection == null && method.getParameterCount() > 1) {
|
||||
log.error("Unable to register {} as an EventHandler. Method has {} arguments, but no EventPreprocessors found to provide DI for type {}", method.toString(), method.getParameterCount(), method.getParameterTypes()[1].toString());
|
||||
continue;
|
||||
}
|
||||
|
||||
if (resultInjection == null && preprocessMethod.getReturnType() != void.class) {
|
||||
log.warn("DI registration for EventHandler {} failed. Injection target not found", method.toString());
|
||||
}
|
||||
|
||||
List<ExecutorLink> eventHandlers = handlers.computeIfAbsent(eventType, s -> new ArrayList<>());
|
||||
eventHandlers.add(new ExecutorLink(annotation.priority().getValue(), annotation.ignoreCancelled(), method, object, preprocessMethod, resultInjection));
|
||||
eventHandlers.sort(Comparator.comparingInt(o -> o.priority));
|
||||
|
||||
preprocessors.remove(method.getName() + ":" + eventType.getSimpleName());
|
||||
}
|
||||
|
||||
for (Map.Entry<String, Method> preprocessor : preprocessors.entrySet())
|
||||
log.error("EventPreprocessor ({}) missing target: unable to find target method ({})", preprocessor.getValue(), preprocessor.getKey());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This class describes
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Getter
|
||||
static class ExecutorLink {
|
||||
private final int priority;
|
||||
private final boolean ignoreCancelled;
|
||||
private final Method method;
|
||||
private final Object object;
|
||||
private final Method preprocessMethod;
|
||||
private final Class resultInjection;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,24 +1,17 @@
|
||||
package mc.core.events.async;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import mc.core.events.BaseEventLoop;
|
||||
import mc.core.events.Event;
|
||||
import mc.core.events.EventHandler;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
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<>();
|
||||
public class AsyncEventLoop extends AdvancedEventLoop {
|
||||
private ExecutorService preEventExecutor = Executors.newSingleThreadExecutor();
|
||||
|
||||
@Override
|
||||
@@ -51,110 +44,14 @@ public class AsyncEventLoop extends BaseEventLoop {
|
||||
|
||||
try {
|
||||
if (link.getResultInjection() != null)
|
||||
link.getMethod().invoke(link.object, event, eventBatch.getInjectionObject(i));
|
||||
link.getMethod().invoke(link.getObject(), event, eventBatch.getInjectionObject(i));
|
||||
else
|
||||
link.getMethod().invoke(link.object, event);
|
||||
link.getMethod().invoke(link.getObject(), event);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
log.error("Exception caught while attempting to dispatch {}.", eventType.getSimpleName(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addEventHandler(Object object) {
|
||||
Map<String, Method> preprocessors = new HashMap<>();
|
||||
|
||||
for (Method method : object.getClass().getDeclaredMethods()) {
|
||||
EventPreprocessor annotation = method.getAnnotation(EventPreprocessor.class);
|
||||
if (annotation == null)
|
||||
continue;
|
||||
|
||||
if (!Modifier.isPublic(method.getModifiers())) {
|
||||
log.error("Unable to register {} as an EventPreprocessor. Method must have a 'private' access modifier.", method.toString());
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
if (method.getParameterCount() != 1) {
|
||||
log.error("Unable to register {} as an EventPreprocessor. Method must have exactly one argument.", method.toString());
|
||||
continue;
|
||||
}
|
||||
|
||||
Class<?> firstParamType = method.getParameterTypes()[0];
|
||||
if (!Event.class.isAssignableFrom(firstParamType)) {
|
||||
log.error("Unable to register {} as an EventPreprocessor. First parameter type must implement 'Event' interface.", method.toString());
|
||||
continue;
|
||||
}
|
||||
|
||||
if (preprocessors.containsKey(annotation.methodName()))
|
||||
log.warn("Attempted to register multiple EventPreprocessors for the event {}. Please note, that only the last one will be registered.", annotation.methodName());
|
||||
preprocessors.put(annotation.methodName() + ":" + firstParamType.getSimpleName(), method);
|
||||
}
|
||||
|
||||
|
||||
for (Method method : object.getClass().getDeclaredMethods()) {
|
||||
EventHandler annotation = method.getAnnotation(EventHandler.class);
|
||||
|
||||
if (annotation == null)
|
||||
continue;
|
||||
|
||||
if (!Modifier.isPublic(method.getModifiers())) {
|
||||
log.error("Unable to register {} as an EventHandler. Method must have a 'private' access modifier.", method.toString());
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
if (method.getParameterCount() == 0) {
|
||||
log.error("Unable to register {} as an EventHandler. Method must at least one argument.", method.toString());
|
||||
continue;
|
||||
}
|
||||
|
||||
Class<?> firstParamType = method.getParameterTypes()[0];
|
||||
if (!Event.class.isAssignableFrom(firstParamType)) {
|
||||
log.error("Unable to register {} as an EventHandler. First parameter type must implement 'Event' interface.", method.toString());
|
||||
continue;
|
||||
}
|
||||
@SuppressWarnings("unchecked") Class<? extends Event> eventType = (Class<? extends Event>) method.getParameterTypes()[0];
|
||||
|
||||
Method preprocessMethod = preprocessors.get(method.getName() + ":" + eventType.getSimpleName());
|
||||
Class resultInjection = null;
|
||||
if (preprocessMethod.getReturnType() != void.class && method.getParameterCount() == 2 && preprocessMethod.getReturnType().equals(method.getParameterTypes()[1]))
|
||||
resultInjection = preprocessMethod.getReturnType();
|
||||
|
||||
if (resultInjection == null && method.getParameterCount() > 1) {
|
||||
log.error("Unable to register {} as an EventHandler. Method has {} arguments, but no EventPreprocessors found to provide DI for type {}", method.toString(), method.getParameterCount(), method.getParameterTypes()[1].toString());
|
||||
continue;
|
||||
}
|
||||
|
||||
if (resultInjection == null && preprocessMethod.getReturnType() != void.class) {
|
||||
log.warn("DI registration for EventHandler {} failed. Injection target not found", method.toString());
|
||||
}
|
||||
|
||||
List<ExecutorLink> eventHandlers = handlers.computeIfAbsent(eventType, s -> new ArrayList<>());
|
||||
eventHandlers.add(new ExecutorLink(annotation.priority().getValue(), annotation.ignoreCancelled(), method, object, preprocessMethod, resultInjection));
|
||||
eventHandlers.sort(Comparator.comparingInt(o -> o.priority));
|
||||
|
||||
preprocessors.remove(method.getName() + ":" + eventType.getSimpleName());
|
||||
}
|
||||
|
||||
for (Map.Entry<String, Method> preprocessor : preprocessors.entrySet())
|
||||
log.error("EventPreprocessor ({}) missing target: unable to find target method ({})", preprocessor.getValue(), preprocessor.getKey());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This class describes
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Getter
|
||||
static class ExecutorLink {
|
||||
private final int priority;
|
||||
private final boolean ignoreCancelled;
|
||||
private final Method method;
|
||||
private final Object object;
|
||||
private final Method preprocessMethod;
|
||||
private final Class resultInjection;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user