scarpet corountines idea
This commit is contained in:
1 parent
23ed35a398
commit
146573803c
11 files changed
+284
-17
No files matched your search
@@ -3,13 +3,21 @@ package carpet.script.value;
|
||||
import carpet.script.exception.InternalExpressionException;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class AbstractListValue extends Value implements Iterable<Value>
|
||||
{
|
||||
public List<Value> unpack()
|
||||
{
|
||||
List<Value> retVal = Lists.newArrayList(iterator());
|
||||
ArrayList<Value> retVal = Lists.newArrayList();
|
||||
for (Value value : this)
|
||||
{
|
||||
if (value != Value.EOL)
|
||||
{
|
||||
retVal.add(value);
|
||||
}
|
||||
}
|
||||
fatality();
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@@ -22,6 +22,8 @@ import java.util.function.Consumer;
|
||||
import net.minecraft.nbt.StringTag;
|
||||
import net.minecraft.nbt.Tag;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class FunctionValue extends Value implements Fluff.ILazyFunction
|
||||
{
|
||||
private final Expression expression;
|
||||
@@ -158,7 +160,7 @@ public class FunctionValue extends Value implements Fluff.ILazyFunction
|
||||
{
|
||||
try
|
||||
{
|
||||
return execute(c, type, expression, token, params);
|
||||
return execute(c, type, expression, token, params, null);
|
||||
}
|
||||
catch (ExpressionException exc)
|
||||
{
|
||||
@@ -214,10 +216,10 @@ public class FunctionValue extends Value implements Fluff.ILazyFunction
|
||||
public LazyValue lazyEval(Context c, Context.Type type, Expression e, Tokenizer.Token t, List<LazyValue> lazyParams)
|
||||
{
|
||||
List<Value> resolvedParams = unpackArgs(lazyParams, c);
|
||||
return execute(c, type, e, t, resolvedParams);
|
||||
return execute(c, type, e, t, resolvedParams, null);
|
||||
}
|
||||
|
||||
public LazyValue execute(Context c, Context.Type type, Expression e, Tokenizer.Token t, List<Value> params)
|
||||
public LazyValue execute(Context c, Context.Type type, Expression e, Tokenizer.Token t, List<Value> params, @Nullable ThreadValue freshNewCallingThread)
|
||||
{
|
||||
assertArgsOk(params, fixedArgs -> {
|
||||
if (fixedArgs) // wrong number of args for fixed args
|
||||
@@ -237,6 +239,10 @@ public class FunctionValue extends Value implements Fluff.ILazyFunction
|
||||
);
|
||||
});
|
||||
Context newFrame = c.recreate();
|
||||
if (freshNewCallingThread != null)
|
||||
{
|
||||
newFrame.setThreadContext(freshNewCallingThread);
|
||||
}
|
||||
|
||||
if (outerState != null)
|
||||
{
|
||||
|
||||
@@ -137,7 +137,12 @@ public abstract class LazyListValue extends AbstractListValue implements Iterato
|
||||
public List<Value> unroll()
|
||||
{
|
||||
List<Value> result = new ArrayList<>();
|
||||
this.forEachRemaining(result::add);
|
||||
this.forEachRemaining(v -> {
|
||||
if (v != Value.EOL)
|
||||
{
|
||||
result.add(v);
|
||||
}
|
||||
});
|
||||
fatality();
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -7,34 +7,39 @@ import carpet.script.exception.ExitStatement;
|
||||
import carpet.script.exception.ExpressionException;
|
||||
import carpet.script.exception.InternalExpressionException;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Deque;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import net.minecraft.nbt.Tag;
|
||||
|
||||
public class ThreadValue extends Value
|
||||
public class ThreadValue extends LazyListValue
|
||||
{
|
||||
private final CompletableFuture<Value> taskFuture;
|
||||
private final long id;
|
||||
private static long sequence = 0L;
|
||||
|
||||
public ThreadValue(CompletableFuture<Value> taskFuture)
|
||||
{
|
||||
this.taskFuture = taskFuture;
|
||||
this.id = sequence++;
|
||||
}
|
||||
private final Deque<Value> coState = new ArrayDeque<>();
|
||||
private final AtomicReference<Value> coLock = new AtomicReference<>(Value.EOL);
|
||||
public final boolean isCoroutine;
|
||||
|
||||
public ThreadValue(Value pool, FunctionValue function, Expression expr, Tokenizer.Token token, Context ctx, List<Value> args)
|
||||
{
|
||||
this(getCompletableFutureFromFunction(pool, function, expr, token, ctx, args));
|
||||
this.id = sequence++;
|
||||
this.isCoroutine = ctx.host.canSynchronouslyExecute();
|
||||
this.taskFuture = getCompletableFutureFromFunction(pool, function, expr, token, ctx, args);
|
||||
|
||||
Thread.yield();
|
||||
}
|
||||
|
||||
public static CompletableFuture<Value> getCompletableFutureFromFunction(Value pool, FunctionValue function, Expression expr, Tokenizer.Token token, Context ctx, List<Value> args)
|
||||
public CompletableFuture<Value> getCompletableFutureFromFunction(Value pool, FunctionValue function, Expression expr, Tokenizer.Token token, Context ctx, List<Value> args)
|
||||
{
|
||||
ExecutorService executor = ctx.host.getExecutor(pool);
|
||||
ThreadValue callingThread = isCoroutine ? this : null;
|
||||
if (executor == null)
|
||||
{
|
||||
// app is shutting down - no more threads can be spawned.
|
||||
@@ -45,7 +50,7 @@ public class ThreadValue extends Value
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
try
|
||||
{
|
||||
return function.execute(ctx, Context.NONE, expr, token, args).evalValue(ctx);
|
||||
return function.execute(ctx, Context.NONE, expr, token, args, callingThread).evalValue(ctx);
|
||||
}
|
||||
catch (ExitStatement exit)
|
||||
{
|
||||
@@ -137,4 +142,143 @@ public class ThreadValue extends Value
|
||||
{
|
||||
return "task";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fatality()
|
||||
{
|
||||
// we signal that won't be interested in the co-thread anymore
|
||||
// but threads run client code, so we can't just kill them
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset()
|
||||
{
|
||||
//throw new InternalExpressionException("Illegal operation on a task");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Iterator<Value> iterator()
|
||||
{
|
||||
if (!isCoroutine)
|
||||
{
|
||||
throw new InternalExpressionException("Cannot iterate over this task");
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext()
|
||||
{
|
||||
return !(coState.isEmpty() && taskFuture.isDone());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Value next()
|
||||
{
|
||||
Value popped = null;
|
||||
synchronized (coState)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
if (!coState.isEmpty())
|
||||
{
|
||||
popped = coState.pop();
|
||||
}
|
||||
else if (taskFuture.isDone())
|
||||
{
|
||||
popped = Value.EOL;
|
||||
}
|
||||
if (popped != null)
|
||||
{
|
||||
break;
|
||||
}
|
||||
try
|
||||
{
|
||||
coState.wait(1);
|
||||
}
|
||||
catch (InterruptedException ignored)
|
||||
{
|
||||
}
|
||||
}
|
||||
coState.notifyAll();
|
||||
}
|
||||
return popped;
|
||||
}
|
||||
|
||||
public void send(Value value)
|
||||
{
|
||||
synchronized (coLock)
|
||||
{
|
||||
coLock.set(value);
|
||||
coLock.notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
public Value ping(Value value, boolean lock)
|
||||
{
|
||||
synchronized (coState)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!lock)
|
||||
{
|
||||
coState.add(value);
|
||||
return Value.NULL;
|
||||
}
|
||||
while (true)
|
||||
{
|
||||
if (coState.isEmpty())
|
||||
{
|
||||
coState.add(value);
|
||||
break;
|
||||
}
|
||||
try
|
||||
{
|
||||
coState.wait(1);
|
||||
}
|
||||
|
||||
catch (InterruptedException ignored)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
coState.notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
// locked mode
|
||||
|
||||
synchronized (coLock)
|
||||
{
|
||||
Value ret;
|
||||
try
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
Value current = coLock.get();
|
||||
if (current != Value.EOL)
|
||||
{
|
||||
ret = current;
|
||||
coLock.set(Value.EOL);
|
||||
break;
|
||||
}
|
||||
try
|
||||
{
|
||||
coLock.wait(1);
|
||||
}
|
||||
catch (InterruptedException ignored)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
coLock.notifyAll();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import net.minecraft.nbt.Tag;
|
||||
public class UndefValue extends NullValue
|
||||
{
|
||||
public static final UndefValue UNDEF = new UndefValue();
|
||||
public static final UndefValue EOL = new UndefValue();
|
||||
|
||||
private RuntimeException getError()
|
||||
{
|
||||
|
||||
@@ -25,6 +25,7 @@ public abstract class Value implements Comparable<Value>, Cloneable
|
||||
|
||||
public static final NullValue NULL = NullValue.NULL;
|
||||
public static final UndefValue UNDEF = UndefValue.UNDEF;
|
||||
public static final UndefValue EOL = UndefValue.EOL;
|
||||
|
||||
public String boundVariable;
|
||||
|
||||
|
||||
Reference in new issue
Block a user