task: use lambdas for scheduled method invokes

This commit is contained in:
Adam
2020-01-20 10:20:16 -05:00
parent 769e7d2ff1
commit f37c981197
3 changed files with 53 additions and 44 deletions

View File

@@ -38,6 +38,11 @@ import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.Module;
import java.io.IOException;
import java.lang.invoke.CallSite;
import java.lang.invoke.LambdaMetafactory;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
@@ -57,8 +62,6 @@ import javax.inject.Singleton;
import javax.swing.SwingUtilities;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import net.runelite.client.events.SessionClose;
import net.runelite.client.events.SessionOpen;
import net.runelite.client.RuneLite;
import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigManager;
@@ -66,11 +69,14 @@ import net.runelite.client.config.RuneLiteConfig;
import net.runelite.client.eventbus.EventBus;
import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.events.PluginChanged;
import net.runelite.client.events.SessionClose;
import net.runelite.client.events.SessionOpen;
import net.runelite.client.task.Schedule;
import net.runelite.client.task.ScheduledMethod;
import net.runelite.client.task.Scheduler;
import net.runelite.client.ui.SplashScreen;
import net.runelite.client.util.GameEventManager;
import net.runelite.client.util.ReflectUtil;
@Singleton
@Slf4j
@@ -501,7 +507,30 @@ public class PluginManager
continue;
}
ScheduledMethod scheduledMethod = new ScheduledMethod(schedule, method, plugin);
Runnable runnable = null;
try
{
final Class<?> clazz = method.getDeclaringClass();
final MethodHandles.Lookup caller = ReflectUtil.privateLookupIn(clazz);
final MethodType subscription = MethodType.methodType(method.getReturnType(), method.getParameterTypes());
final MethodHandle target = caller.findVirtual(clazz, method.getName(), subscription);
final CallSite site = LambdaMetafactory.metafactory(
caller,
"run",
MethodType.methodType(Runnable.class, clazz),
subscription,
target,
subscription);
final MethodHandle factory = site.getTarget();
runnable = (Runnable) factory.bindTo(plugin).invokeExact();
}
catch (Throwable e)
{
log.warn("Unable to create lambda for method {}", method, e);
}
ScheduledMethod scheduledMethod = new ScheduledMethod(schedule, method, plugin, runnable);
log.debug("Scheduled task {}", scheduledMethod);
scheduler.addScheduledMethod(scheduledMethod);

View File

@@ -26,49 +26,22 @@ package net.runelite.client.task;
import java.lang.reflect.Method;
import java.time.Instant;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import lombok.ToString;
@RequiredArgsConstructor
@ToString
@Getter
public class ScheduledMethod
{
private final Schedule schedule;
private final Method method;
private final Object object;
@EqualsAndHashCode.Exclude
private final Runnable lambda;
@Setter
private Instant last = Instant.now();
public ScheduledMethod(Schedule schedule, Method method, Object object)
{
this.schedule = schedule;
this.method = method;
this.object = object;
}
@Override
public String toString()
{
return "ScheduledMethod{" + "schedule=" + schedule + ", method=" + method + ", object=" + object + '}';
}
public Schedule getSchedule()
{
return schedule;
}
public Method getMethod()
{
return method;
}
public Object getObject()
{
return object;
}
public Instant getLast()
{
return last;
}
public void setLast(Instant last)
{
this.last = last;
}
}

View File

@@ -93,11 +93,18 @@ public class Scheduler
private void run(ScheduledMethod scheduledMethod)
{
Method method = scheduledMethod.getMethod();
try
{
method.invoke(scheduledMethod.getObject());
Runnable lambda = scheduledMethod.getLambda();
if (lambda != null)
{
lambda.run();
}
else
{
Method method = scheduledMethod.getMethod();
method.invoke(scheduledMethod.getObject());
}
}
catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex)
{