mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2024-11-16 14:54:54 +00:00
Update the executor to work with the new calling system
This commit is contained in:
parent
f23acef2dd
commit
4b741739e8
@ -0,0 +1,87 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2018. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.core.lua;
|
||||
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.api.lua.ICallContext;
|
||||
import dan200.computercraft.api.lua.ILuaTask;
|
||||
import dan200.computercraft.api.lua.LuaException;
|
||||
import dan200.computercraft.core.computer.Computer;
|
||||
import dan200.computercraft.core.computer.ITask;
|
||||
import dan200.computercraft.core.computer.MainThread;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
class CobaltCallContext implements ICallContext
|
||||
{
|
||||
private final Computer computer;
|
||||
|
||||
CobaltCallContext( Computer computer )
|
||||
{
|
||||
this.computer = computer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long issueMainThreadTask( @Nonnull final ILuaTask task ) throws LuaException
|
||||
{
|
||||
// Issue command
|
||||
final long taskID = MainThread.getUniqueTaskID();
|
||||
final ITask iTask = new ITask()
|
||||
{
|
||||
@Override
|
||||
public Computer getOwner()
|
||||
{
|
||||
return computer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute()
|
||||
{
|
||||
try
|
||||
{
|
||||
Object[] results = task.execute();
|
||||
if( results != null )
|
||||
{
|
||||
Object[] eventArguments = new Object[results.length + 2];
|
||||
eventArguments[0] = taskID;
|
||||
eventArguments[1] = true;
|
||||
System.arraycopy( results, 0, eventArguments, 2, results.length );
|
||||
computer.queueEvent( "task_complete", eventArguments );
|
||||
}
|
||||
else
|
||||
{
|
||||
computer.queueEvent( "task_complete", new Object[]{ taskID, true } );
|
||||
}
|
||||
}
|
||||
catch( LuaException e )
|
||||
{
|
||||
computer.queueEvent( "task_complete", new Object[]{
|
||||
taskID, false, e.getMessage()
|
||||
} );
|
||||
}
|
||||
catch( Throwable t )
|
||||
{
|
||||
if( ComputerCraft.logPeripheralErrors )
|
||||
{
|
||||
ComputerCraft.log.error( "Error running task", t );
|
||||
}
|
||||
computer.queueEvent( "task_complete", new Object[]{
|
||||
taskID, false, "Java Exception Thrown: " + t.toString()
|
||||
} );
|
||||
}
|
||||
}
|
||||
};
|
||||
if( MainThread.queueTask( iTask ) )
|
||||
{
|
||||
return taskID;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new LuaException( "Task limit exceeded" );
|
||||
}
|
||||
}
|
||||
}
|
@ -6,39 +6,57 @@
|
||||
|
||||
package dan200.computercraft.core.lua;
|
||||
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.api.lua.ILuaContext;
|
||||
import dan200.computercraft.api.lua.ILuaContextTask;
|
||||
import dan200.computercraft.api.lua.ILuaTask;
|
||||
import dan200.computercraft.api.lua.LuaException;
|
||||
import dan200.computercraft.core.computer.Computer;
|
||||
import dan200.computercraft.core.computer.ITask;
|
||||
import dan200.computercraft.core.computer.MainThread;
|
||||
import org.squiddev.cobalt.LuaError;
|
||||
import org.squiddev.cobalt.LuaState;
|
||||
import org.squiddev.cobalt.LuaThread;
|
||||
import org.squiddev.cobalt.UnwindThrowable;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.SynchronousQueue;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
class CobaltLuaContext implements ILuaContext
|
||||
/**
|
||||
* An ugly wrapper for {@link ILuaContext} style calls, which executes them on a separate thread.
|
||||
*/
|
||||
class CobaltLuaContext extends CobaltCallContext implements ILuaContext
|
||||
{
|
||||
private final Computer computer;
|
||||
private static final ThreadGroup group = new ThreadGroup( "ComputerCraft-Lua" );
|
||||
private static final AtomicInteger threadCounter = new AtomicInteger();
|
||||
private static final ExecutorService threads = new ThreadPoolExecutor(
|
||||
4, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<>(),
|
||||
task -> {
|
||||
Thread thread = new Thread( group, task, group.getName() + "-" + threadCounter.incrementAndGet() );
|
||||
if( !thread.isDaemon() ) thread.setDaemon( true );
|
||||
if( thread.getPriority() != Thread.NORM_PRIORITY ) thread.setPriority( Thread.NORM_PRIORITY );
|
||||
return thread;
|
||||
}
|
||||
);
|
||||
|
||||
boolean done = false;
|
||||
Object[] values;
|
||||
LuaError exception;
|
||||
final Semaphore yield = new Semaphore();
|
||||
final Semaphore resume = new Semaphore();
|
||||
private boolean done = false;
|
||||
private Object[] values;
|
||||
private LuaError exception;
|
||||
private final Semaphore yield = new Semaphore();
|
||||
private final Semaphore resume = new Semaphore();
|
||||
private WeakReference<LuaThread> thread;
|
||||
|
||||
public CobaltLuaContext( Computer computer, LuaState state )
|
||||
CobaltLuaContext( Computer computer, LuaState state )
|
||||
{
|
||||
this.computer = computer;
|
||||
super( computer );
|
||||
this.thread = state.getCurrentThread().getReference();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
@Deprecated
|
||||
public Object[] pullEvent( String filter ) throws LuaException, InterruptedException
|
||||
{
|
||||
Object[] results = pullEventRaw( filter );
|
||||
@ -51,6 +69,7 @@ class CobaltLuaContext implements ILuaContext
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
@Deprecated
|
||||
public Object[] pullEventRaw( String filter ) throws InterruptedException
|
||||
{
|
||||
return yield( new Object[]{ filter } );
|
||||
@ -58,6 +77,7 @@ class CobaltLuaContext implements ILuaContext
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
@Deprecated
|
||||
public Object[] yield( Object[] yieldArgs ) throws InterruptedException
|
||||
{
|
||||
if( done ) throw new IllegalStateException( "Cannot yield when complete" );
|
||||
@ -76,66 +96,7 @@ class CobaltLuaContext implements ILuaContext
|
||||
}
|
||||
|
||||
@Override
|
||||
public long issueMainThreadTask( @Nonnull final ILuaTask task ) throws LuaException
|
||||
{
|
||||
// Issue command
|
||||
final long taskID = MainThread.getUniqueTaskID();
|
||||
final ITask iTask = new ITask()
|
||||
{
|
||||
@Override
|
||||
public Computer getOwner()
|
||||
{
|
||||
return computer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute()
|
||||
{
|
||||
try
|
||||
{
|
||||
Object[] results = task.execute();
|
||||
if( results != null )
|
||||
{
|
||||
Object[] eventArguments = new Object[results.length + 2];
|
||||
eventArguments[0] = taskID;
|
||||
eventArguments[1] = true;
|
||||
System.arraycopy( results, 0, eventArguments, 2, results.length );
|
||||
computer.queueEvent( "task_complete", eventArguments );
|
||||
}
|
||||
else
|
||||
{
|
||||
computer.queueEvent( "task_complete", new Object[]{ taskID, true } );
|
||||
}
|
||||
}
|
||||
catch( LuaException e )
|
||||
{
|
||||
computer.queueEvent( "task_complete", new Object[]{
|
||||
taskID, false, e.getMessage()
|
||||
} );
|
||||
}
|
||||
catch( Throwable t )
|
||||
{
|
||||
if( ComputerCraft.logPeripheralErrors )
|
||||
{
|
||||
ComputerCraft.log.error( "Error running task", t );
|
||||
}
|
||||
computer.queueEvent( "task_complete", new Object[]{
|
||||
taskID, false, "Java Exception Thrown: " + t.toString()
|
||||
} );
|
||||
}
|
||||
}
|
||||
};
|
||||
if( MainThread.queueTask( iTask ) )
|
||||
{
|
||||
return taskID;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new LuaException( "Task limit exceeded" );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public Object[] executeMainThreadTask( @Nonnull final ILuaTask task ) throws LuaException, InterruptedException
|
||||
{
|
||||
// Issue task
|
||||
@ -172,4 +133,58 @@ class CobaltLuaContext implements ILuaContext
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void execute( ILuaContextTask task )
|
||||
{
|
||||
threads.submit( () -> {
|
||||
try
|
||||
{
|
||||
values = task.execute( this );
|
||||
}
|
||||
catch( LuaException e )
|
||||
{
|
||||
exception = new LuaError( e.getMessage(), e.getLevel() );
|
||||
}
|
||||
catch( InterruptedException e )
|
||||
{
|
||||
exception = new LuaError( "Java Exception Thrown: " + e.toString(), 0 );
|
||||
}
|
||||
finally
|
||||
{
|
||||
done = true;
|
||||
yield.signal();
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
Object[] resume( LuaState state, CobaltLuaMachine machine, Object[] args ) throws LuaError, UnwindThrowable
|
||||
{
|
||||
values = args;
|
||||
resume.signal();
|
||||
|
||||
if( !done )
|
||||
{
|
||||
try
|
||||
{
|
||||
yield.await();
|
||||
}
|
||||
catch( InterruptedException e )
|
||||
{
|
||||
state.debug.onReturn();
|
||||
throw new LuaError( "Java Exception Thrown: " + e.toString(), 0 );
|
||||
}
|
||||
}
|
||||
|
||||
if( done )
|
||||
{
|
||||
state.debug.onReturn();
|
||||
if( exception != null ) throw exception;
|
||||
return values;
|
||||
}
|
||||
else
|
||||
{
|
||||
LuaThread.yield( state, machine.toValues( values ) );
|
||||
throw new IllegalStateException( "Unreachable" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -291,20 +291,18 @@ public class CobaltLuaMachine implements ILuaMachine
|
||||
{
|
||||
LuaTable table = new LuaTable();
|
||||
String[] methods = object.getMethodNames();
|
||||
for( int i = 0; i < methods.length; ++i )
|
||||
for( int method = 0; method < methods.length; method++ )
|
||||
{
|
||||
if( methods[ i ] != null )
|
||||
if( methods[method] != null )
|
||||
{
|
||||
final int method = i;
|
||||
final ILuaObject apiObject = object;
|
||||
final String methodName = methods[ i ];
|
||||
table.rawset( methodName, new CobaltWrapperFunction( this, m_computer, apiObject, method, methodName ) );
|
||||
final String methodName = methods[method];
|
||||
table.rawset( methodName, new CobaltWrapperFunction( this, m_computer, object, method, methodName ) );
|
||||
}
|
||||
}
|
||||
return table;
|
||||
}
|
||||
|
||||
LuaValue toValue( Object object, Map<Object, LuaValue> values )
|
||||
private LuaValue toValue( Object object, Map<Object, LuaValue> values )
|
||||
{
|
||||
if( object == null )
|
||||
{
|
||||
@ -382,7 +380,7 @@ public class CobaltLuaMachine implements ILuaMachine
|
||||
return varargsOf( values );
|
||||
}
|
||||
|
||||
static Object toObject( LuaValue value, Map<LuaValue, Object> objects )
|
||||
private static Object toObject( LuaValue value, Map<LuaValue, Object> objects )
|
||||
{
|
||||
switch( value.type() )
|
||||
{
|
||||
|
@ -7,8 +7,10 @@
|
||||
package dan200.computercraft.core.lua;
|
||||
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.api.lua.ILuaFunction;
|
||||
import dan200.computercraft.api.lua.ILuaObject;
|
||||
import dan200.computercraft.api.lua.LuaException;
|
||||
import dan200.computercraft.api.lua.MethodResult;
|
||||
import dan200.computercraft.core.computer.Computer;
|
||||
import org.squiddev.cobalt.*;
|
||||
import org.squiddev.cobalt.debug.DebugFrame;
|
||||
@ -16,28 +18,14 @@ import org.squiddev.cobalt.debug.DebugHandler;
|
||||
import org.squiddev.cobalt.debug.DebugState;
|
||||
import org.squiddev.cobalt.function.VarArgFunction;
|
||||
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.SynchronousQueue;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Deque;
|
||||
|
||||
class CobaltWrapperFunction extends VarArgFunction implements Resumable<CobaltLuaContext>
|
||||
class CobaltWrapperFunction extends VarArgFunction implements Resumable<CobaltWrapperFunction.State>
|
||||
{
|
||||
private static final ThreadGroup group = new ThreadGroup( "ComputerCraft-Lua" );
|
||||
private static final AtomicInteger threadCounter = new AtomicInteger();
|
||||
private static final ExecutorService threads = new ThreadPoolExecutor(
|
||||
4, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<>(),
|
||||
task -> {
|
||||
Thread thread = new Thread( group, task, group.getName() + "-" + threadCounter.incrementAndGet() );
|
||||
if( !thread.isDaemon() ) thread.setDaemon( true );
|
||||
if( thread.getPriority() != Thread.NORM_PRIORITY ) thread.setPriority( Thread.NORM_PRIORITY );
|
||||
return thread;
|
||||
}
|
||||
);
|
||||
|
||||
private final CobaltLuaMachine machine;
|
||||
private final Computer computer;
|
||||
private final CobaltCallContext callContext;
|
||||
|
||||
private final ILuaObject delegate;
|
||||
private final int method;
|
||||
@ -47,6 +35,7 @@ class CobaltWrapperFunction extends VarArgFunction implements Resumable<CobaltLu
|
||||
{
|
||||
this.machine = machine;
|
||||
this.computer = computer;
|
||||
this.callContext = new CobaltCallContext( computer );
|
||||
this.delegate = delegate;
|
||||
this.method = method;
|
||||
this.methodName = methodName;
|
||||
@ -55,94 +44,241 @@ class CobaltWrapperFunction extends VarArgFunction implements Resumable<CobaltLu
|
||||
@Override
|
||||
public Varargs invoke( final LuaState state, Varargs args ) throws LuaError, UnwindThrowable
|
||||
{
|
||||
Object[] arguments = CobaltLuaMachine.toObjects( args, 1 );
|
||||
CobaltLuaContext context = new CobaltLuaContext( computer, state );
|
||||
|
||||
DebugHandler handler = state.debug;
|
||||
DebugState ds = handler.getDebugState();
|
||||
DebugFrame di = handler.onCall( ds, this );
|
||||
di.state = context;
|
||||
|
||||
threads.submit( () -> {
|
||||
try
|
||||
MethodResult future;
|
||||
try
|
||||
{
|
||||
future = delegate.callMethod( callContext, method, CobaltLuaMachine.toObjects( args, 1 ) );
|
||||
}
|
||||
catch( LuaException e )
|
||||
{
|
||||
throw new LuaError( e.getMessage(), e.getLevel() );
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
if( ComputerCraft.logPeripheralErrors )
|
||||
{
|
||||
context.values = delegate.callMethod( context, method, arguments );
|
||||
ComputerCraft.log.error( "Error calling " + methodName + " on " + delegate, e );
|
||||
}
|
||||
catch( LuaException e )
|
||||
throw new LuaError( "Java Exception Thrown: " + e.toString(), 0 );
|
||||
}
|
||||
|
||||
if( future == null )
|
||||
{
|
||||
ComputerCraft.log.error( "Null result from " + delegate );
|
||||
throw new LuaError( "Java Exception Thrown: Null result" );
|
||||
}
|
||||
|
||||
State context = new State();
|
||||
try
|
||||
{
|
||||
return runFuture( state, context, future );
|
||||
}
|
||||
catch( UnwindThrowable e )
|
||||
{
|
||||
// Push our state onto the stack if need-be.
|
||||
DebugHandler handler = state.debug;
|
||||
DebugState ds = handler.getDebugState();
|
||||
DebugFrame di = handler.onCall( ds, this );
|
||||
di.state = context;
|
||||
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Varargs resume( LuaState state, State context, Varargs args ) throws LuaError, UnwindThrowable
|
||||
{
|
||||
try
|
||||
{
|
||||
Varargs result = doResume( state, context, args );
|
||||
state.debug.onReturn();
|
||||
return result;
|
||||
}
|
||||
catch( LuaError e )
|
||||
{
|
||||
state.debug.onReturn();
|
||||
throw e;
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
state.debug.onReturn();
|
||||
throw new LuaError( e );
|
||||
}
|
||||
}
|
||||
|
||||
private Varargs doResume( LuaState state, State context, Varargs args ) throws LuaError, UnwindThrowable
|
||||
{
|
||||
MethodResult future = context.pending;
|
||||
if( future instanceof MethodResult.OnEvent )
|
||||
{
|
||||
MethodResult.OnEvent onEvent = (MethodResult.OnEvent) future;
|
||||
if( !onEvent.isRaw() && args.first().toString().equals( "terminate" ) )
|
||||
{
|
||||
context.exception = new LuaError( e );
|
||||
throw new LuaError( "Terminated", 0 );
|
||||
}
|
||||
catch( InterruptedException e )
|
||||
|
||||
return runCallback( state, context, CobaltLuaMachine.toObjects( args, 1 ) );
|
||||
}
|
||||
else if( future instanceof MethodResult.OnMainThread )
|
||||
{
|
||||
if( args.arg( 2 ).isNumber() && args.arg( 3 ).isBoolean() && args.arg( 2 ).toLong() == context.taskId )
|
||||
{
|
||||
if( ComputerCraft.logPeripheralErrors )
|
||||
if( args.arg( 3 ).toBoolean() )
|
||||
{
|
||||
ComputerCraft.log.error( "Error calling " + methodName + " on " + delegate, e );
|
||||
// Extract the return values from the event and return them
|
||||
return runCallback( state, context, CobaltLuaMachine.toObjects( args, 4 ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Extract the error message from the event and raise it
|
||||
throw new LuaError( args.arg( 4 ) );
|
||||
}
|
||||
context.exception = new LuaError( "Java Exception Thrown: " + e.toString(), 0 );
|
||||
}
|
||||
finally
|
||||
{
|
||||
context.done = true;
|
||||
context.yield.signal();
|
||||
}
|
||||
} );
|
||||
|
||||
try
|
||||
{
|
||||
return handleResult( state, context );
|
||||
}
|
||||
catch( InterruptedException e )
|
||||
{
|
||||
throw new LuaError( e );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Varargs resume( LuaState state, CobaltLuaContext context, Varargs value ) throws LuaError, UnwindThrowable
|
||||
{
|
||||
context.values = CobaltLuaMachine.toObjects( value, 0 );
|
||||
context.resume.signal();
|
||||
try
|
||||
{
|
||||
return handleResult( state, context );
|
||||
}
|
||||
catch( InterruptedException e )
|
||||
{
|
||||
throw new LuaError( e );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Varargs resumeError( LuaState state, CobaltLuaContext context, LuaError error ) throws LuaError
|
||||
{
|
||||
DebugHandler handler = state.debug;
|
||||
handler.onReturn( handler.getDebugState() );
|
||||
throw error;
|
||||
}
|
||||
|
||||
private Varargs handleResult( LuaState state, CobaltLuaContext context ) throws InterruptedException, LuaError, UnwindThrowable
|
||||
{
|
||||
// We may be done if we yield when handling errors
|
||||
if( !context.done ) context.yield.await();
|
||||
|
||||
if( context.done )
|
||||
{
|
||||
if( context.exception != null )
|
||||
{
|
||||
context.exception.fillTraceback( state );
|
||||
state.debug.onReturn();
|
||||
throw context.exception;
|
||||
}
|
||||
else
|
||||
{
|
||||
state.debug.onReturn();
|
||||
return machine.toValues( context.values );
|
||||
LuaThread.yield( state, ValueFactory.valueOf( "task_complete" ) );
|
||||
throw new IllegalStateException( "Unreachable" );
|
||||
}
|
||||
}
|
||||
else if( future instanceof MethodResult.WithLuaContext )
|
||||
{
|
||||
return runCallback( state, context, context.luaContext.resume( state, machine, CobaltLuaMachine.toObjects( args, 1 ) ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
LuaThread.yield( state, machine.toValues( context.values ) );
|
||||
throw new AssertionError( "Unreachable code" );
|
||||
ComputerCraft.log.error( "Unknown method result " + future );
|
||||
throw new LuaError( "Java Exception Thrown: Unknown method result" );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Varargs resumeError( LuaState state, State context, LuaError error ) throws LuaError
|
||||
{
|
||||
state.debug.onReturn();
|
||||
throw error;
|
||||
}
|
||||
|
||||
private Varargs runFuture( LuaState state, State context, MethodResult future ) throws LuaError, UnwindThrowable
|
||||
{
|
||||
Deque<ILuaFunction> callbacks = context.callbacks;
|
||||
while( true )
|
||||
{
|
||||
if( future instanceof MethodResult.AndThen )
|
||||
{
|
||||
MethodResult.AndThen then = ((MethodResult.AndThen) future);
|
||||
|
||||
// Thens are "unwrapped", being pushed onto a stack
|
||||
if( callbacks == null ) callbacks = context.callbacks = new ArrayDeque<>();
|
||||
callbacks.addLast( then.getCallback() );
|
||||
|
||||
future = then.getPrevious();
|
||||
}
|
||||
else if( future instanceof MethodResult.Immediate )
|
||||
{
|
||||
Object[] values = ((MethodResult.Immediate) future).getResult();
|
||||
|
||||
// Immediate values values will attempt to call the previous "then", or return if nothing
|
||||
// else needs to be done.
|
||||
ILuaFunction callback = callbacks == null ? null : callbacks.pollLast();
|
||||
if( callback == null ) return machine.toValues( values );
|
||||
|
||||
future = runFunction( callback, values );
|
||||
}
|
||||
else if( future instanceof MethodResult.OnEvent )
|
||||
{
|
||||
MethodResult.OnEvent onEvent = (MethodResult.OnEvent) future;
|
||||
|
||||
// Mark this future as pending and yield
|
||||
context.pending = future;
|
||||
String filter = onEvent.getFilter();
|
||||
LuaThread.yield( state, filter == null ? Constants.NIL : ValueFactory.valueOf( filter ) );
|
||||
throw new IllegalStateException( "Unreachable" );
|
||||
}
|
||||
else if( future instanceof MethodResult.OnMainThread )
|
||||
{
|
||||
MethodResult.OnMainThread onMainThread = (MethodResult.OnMainThread) future;
|
||||
|
||||
// Mark this future as pending and yield
|
||||
context.pending = future;
|
||||
try
|
||||
{
|
||||
context.taskId = callContext.issueMainThreadTask( () -> {
|
||||
context.taskResult = onMainThread.getTask().execute();
|
||||
return null;
|
||||
} );
|
||||
}
|
||||
catch( LuaException e )
|
||||
{
|
||||
throw new LuaError( e.getMessage(), e.getLevel() );
|
||||
}
|
||||
|
||||
LuaThread.yield( state, ValueFactory.valueOf( "task_complete" ) );
|
||||
throw new IllegalStateException( "Unreachable" );
|
||||
}
|
||||
else if( future instanceof MethodResult.WithLuaContext )
|
||||
{
|
||||
MethodResult.WithLuaContext withContext = (MethodResult.WithLuaContext) future;
|
||||
|
||||
// Mark this future as pending and execute on a separate thread.
|
||||
context.pending = future;
|
||||
CobaltLuaContext luaContext = context.luaContext = new CobaltLuaContext( computer, state );
|
||||
luaContext.execute( withContext.getConsumer() );
|
||||
}
|
||||
else
|
||||
{
|
||||
ComputerCraft.log.error( "Unknown method result " + future );
|
||||
throw new LuaError( "Java Exception Thrown: Unknown method result" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Varargs runCallback( LuaState state, State context, Object[] args ) throws LuaError, UnwindThrowable
|
||||
{
|
||||
Deque<ILuaFunction> callbacks = context.callbacks;
|
||||
ILuaFunction callback = callbacks == null ? null : callbacks.pollLast();
|
||||
if( callback == null ) return machine.toValues( args );
|
||||
|
||||
return runFuture( state, context, runFunction( callback, args ) );
|
||||
}
|
||||
|
||||
private MethodResult runFunction( ILuaFunction func, Object[] args ) throws LuaError
|
||||
{
|
||||
MethodResult result;
|
||||
try
|
||||
{
|
||||
result = func.call( args );
|
||||
}
|
||||
catch( LuaException e )
|
||||
{
|
||||
throw new LuaError( e.getMessage(), e.getLevel() );
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
if( ComputerCraft.logPeripheralErrors )
|
||||
{
|
||||
ComputerCraft.log.error( "Error calling " + methodName + " on " + delegate, e );
|
||||
}
|
||||
throw new LuaError( "Java Exception Thrown: " + e.toString(), 0 );
|
||||
}
|
||||
|
||||
if( result == null )
|
||||
{
|
||||
ComputerCraft.log.error( "Null result from " + func );
|
||||
throw new LuaError( "Java Exception Thrown: Null result" );
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static class State
|
||||
{
|
||||
Deque<ILuaFunction> callbacks;
|
||||
|
||||
MethodResult pending;
|
||||
|
||||
CobaltLuaContext luaContext;
|
||||
|
||||
long taskId;
|
||||
MethodResult taskResult;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user