resolved joins from main thread as illegal

This commit is contained in:
gnembon committed 2019-12-17 14:41:47 -04:00
1 parent 3295ca2af9
commit 2ff7988251
3 files changed
+25 -33

No files matched your search

@@ -10,6 +10,7 @@ import carpet.script.exception.CarpetExpressionException;
import carpet.script.exception.ExitStatement; import carpet.script.exception.ExitStatement;
import carpet.script.exception.ExpressionException; import carpet.script.exception.ExpressionException;
import carpet.script.exception.InternalExpressionException; import carpet.script.exception.InternalExpressionException;
import carpet.CarpetSettings;
import carpet.script.value.BlockValue; import carpet.script.value.BlockValue;
import carpet.script.value.EntityValue; import carpet.script.value.EntityValue;
import carpet.script.value.FunctionValue; import carpet.script.value.FunctionValue;
@@ -19,8 +20,8 @@ import carpet.script.value.NBTSerializableValue;
import carpet.script.value.NullValue; import carpet.script.value.NullValue;
import carpet.script.value.NumericValue; import carpet.script.value.NumericValue;
import carpet.script.value.StringValue; import carpet.script.value.StringValue;
import carpet.script.value.ThreadValue;
import carpet.script.value.Value; import carpet.script.value.Value;
import carpet.CarpetSettings;
import carpet.utils.BlockInfo; import carpet.utils.BlockInfo;
import carpet.utils.Messenger; import carpet.utils.Messenger;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
@@ -101,7 +102,6 @@ import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.function.BiFunction; import java.util.function.BiFunction;
import java.util.function.Predicate; import java.util.function.Predicate;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@@ -3006,6 +3006,17 @@ public class CarpetExpression
return (_c, _t) -> res; // pass through for variables return (_c, _t) -> res; // pass through for variables
}); });
//"overidden" native call to cancel if on main thread
this.expr.addLazyFunction("join_task", 1, (c, t, lv) -> {
if (((CarpetContext)c).s.getMinecraftServer().isOnThread())
throw new InternalExpressionException("'join_task' cannot be called from main thread to avoid deadlocks");
Value v = lv.get(0).evalValue(c);
if (!(v instanceof ThreadValue))
throw new InternalExpressionException("'join_task' could only be used with a task value");
Value ret = ((ThreadValue) v).join();
return (_c, _t) -> ret;
});
this.expr.addLazyFunction("logger", 1, (c, t, lv) -> this.expr.addLazyFunction("logger", 1, (c, t, lv) ->
{ {
Value res = lv.get(0).evalValue(c); Value res = lv.get(0).evalValue(c);
+9 -3
View File
@@ -11,7 +11,13 @@ import carpet.script.Fluff.QuadFunction;
import carpet.script.Fluff.QuinnFunction; import carpet.script.Fluff.QuinnFunction;
import carpet.script.Fluff.SexFunction; import carpet.script.Fluff.SexFunction;
import carpet.script.Fluff.TriFunction; import carpet.script.Fluff.TriFunction;
import carpet.script.exception.*; import carpet.script.exception.BreakStatement;
import carpet.script.exception.ContinueStatement;
import carpet.script.exception.ExitStatement;
import carpet.script.exception.ExpressionException;
import carpet.script.exception.InternalExpressionException;
import carpet.script.exception.ReturnStatement;
import carpet.script.exception.ThrowStatement;
import carpet.script.value.AbstractListValue; import carpet.script.value.AbstractListValue;
import carpet.script.value.ContainerValueInterface; import carpet.script.value.ContainerValueInterface;
import carpet.script.value.FunctionSignatureValue; import carpet.script.value.FunctionSignatureValue;
@@ -3040,12 +3046,12 @@ public class Expression implements Cloneable
return ((ThreadValue) v).join(); return ((ThreadValue) v).join();
}); });
addUnaryFunction("stop_task", (v) -> { /*addUnaryFunction("stop_task", (v) -> {
if (!(v instanceof ThreadValue)) if (!(v instanceof ThreadValue))
throw new InternalExpressionException("'join_task' could only be used with a task value"); throw new InternalExpressionException("'join_task' could only be used with a task value");
((ThreadValue) v).stop(); ((ThreadValue) v).stop();
return Value.NULL; return Value.NULL;
}); });*/
addUnaryFunction("is_task_completed", (v) -> { addUnaryFunction("is_task_completed", (v) -> {
if (!(v instanceof ThreadValue)) if (!(v instanceof ThreadValue))
@@ -12,35 +12,23 @@ import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.ThreadPoolExecutor;
import java.util.function.Supplier;
public class ThreadValue extends Value public class ThreadValue extends Value
{ {
private CompletableFuture<Value> taskFuture; private CompletableFuture<Value> taskFuture;
private long id; private long id;
private final Object lock; private final Object lock;
private final boolean[] started;
private Supplier<Value>task;
private static long sequence = 0L; private static long sequence = 0L;
private static final Map<Value,ThreadPoolExecutor> executorServices = new HashMap<>(); private static final Map<Value,ThreadPoolExecutor> executorServices = new HashMap<>();
public ThreadValue(Value pool, FunctionValue function, Expression expr, Tokenizer.Token token, Context ctx) public ThreadValue(Value pool, FunctionValue function, Expression expr, Tokenizer.Token token, Context ctx)
{ {
id = sequence++; id = sequence++;
lock = new Object(); lock = new Object();
started = new boolean[]{false};
task = () ->
{
if (!started[0])
{
started[0] = true;
return function.lazyEval(ctx, Context.NONE, expr, token, Collections.emptyList()).evalValue(ctx);
}
return null;
};
taskFuture = CompletableFuture.supplyAsync( taskFuture = CompletableFuture.supplyAsync(
() -> { synchronized (lock) { return task.get(); } }, () -> { synchronized (lock) {
return function.lazyEval(ctx, Context.NONE, expr, token, Collections.emptyList()).evalValue(ctx);
} },
executorServices.computeIfAbsent(pool, (v) -> (ThreadPoolExecutor)Executors.newCachedThreadPool()) executorServices.computeIfAbsent(pool, (v) -> (ThreadPoolExecutor)Executors.newCachedThreadPool())
); );
Thread.yield(); Thread.yield();
@@ -60,18 +48,6 @@ public class ThreadValue extends Value
public Value join() public Value join()
{ {
if (!started[0])
{
synchronized (lock)
{
if (!started[0])
{
Value res = task.get();
taskFuture.complete(res);
return res;
}
}
}
try try
{ {
return taskFuture.get(); return taskFuture.get();
@@ -93,7 +69,6 @@ public class ThreadValue extends Value
{ {
if (!taskFuture.isDone()) if (!taskFuture.isDone())
{ {
started[0] = true;
taskFuture.complete(Value.NULL); taskFuture.complete(Value.NULL);
} }
} }