Merge branch 'threads' of https://github.com/gnembon/fabric-carpet into threads
This commit is contained in:
commit
ab3334e452
5 files changed
+26
-106
No files matched your search
@@ -1,39 +0,0 @@
|
||||
package carpet.mixins;
|
||||
|
||||
import carpet.script.exception.InternalExpressionException;
|
||||
import carpet.script.value.ThreadValue;
|
||||
import net.minecraft.server.world.ServerChunkManager;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
import net.minecraft.world.chunk.ChunkStatus;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@Mixin(ServerChunkManager.class)
|
||||
public class ServerChunkManager_scarpetThreadingProtectionMixin
|
||||
{
|
||||
@Redirect(method = "getChunk(IILnet/minecraft/world/chunk/ChunkStatus;Z)Lnet/minecraft/world/chunk/Chunk;", at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Ljava/util/concurrent/CompletableFuture;join()Ljava/lang/Object;",
|
||||
ordinal = 0
|
||||
))
|
||||
private Object checkJoiningThreads(CompletableFuture<Chunk> completableFuture)
|
||||
{
|
||||
synchronized (ThreadValue.waitingTreads)
|
||||
{
|
||||
if (ThreadValue.waitingTreads.containsKey(Thread.currentThread()))
|
||||
throw new InternalExpressionException("Cannot join/wait on world accessing thread");
|
||||
ThreadValue.waitingTreads.put(Thread.currentThread(), 1);
|
||||
}
|
||||
Chunk res = completableFuture.join();
|
||||
ThreadValue.waitingTreads.remove(Thread.currentThread());
|
||||
return res;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import carpet.script.exception.CarpetExpressionException;
|
||||
import carpet.script.exception.ExitStatement;
|
||||
import carpet.script.exception.ExpressionException;
|
||||
import carpet.script.exception.InternalExpressionException;
|
||||
import carpet.CarpetSettings;
|
||||
import carpet.script.value.BlockValue;
|
||||
import carpet.script.value.EntityValue;
|
||||
import carpet.script.value.FunctionValue;
|
||||
@@ -19,8 +20,8 @@ import carpet.script.value.NBTSerializableValue;
|
||||
import carpet.script.value.NullValue;
|
||||
import carpet.script.value.NumericValue;
|
||||
import carpet.script.value.StringValue;
|
||||
import carpet.script.value.ThreadValue;
|
||||
import carpet.script.value.Value;
|
||||
import carpet.CarpetSettings;
|
||||
import carpet.utils.BlockInfo;
|
||||
import carpet.utils.Messenger;
|
||||
import com.google.common.collect.Sets;
|
||||
@@ -101,7 +102,6 @@ import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -944,18 +944,14 @@ public class CarpetExpression
|
||||
|
||||
this.expr.addLazyFunction("set", -1, (c, t, lv) ->
|
||||
{
|
||||
CarpetSettings.LOG.error("starting");
|
||||
CarpetContext cc = (CarpetContext)c;
|
||||
ServerWorld world = cc.s.getWorld();
|
||||
if (lv.size() < 2 || lv.size() % 2 == 1)
|
||||
throw new InternalExpressionException("'set' should have at least 2 params and odd attributes");
|
||||
BlockValue.LocatorResult targetLocator = BlockValue.fromParams(cc, lv, 0);
|
||||
BlockValue.LocatorResult sourceLocator = BlockValue.fromParams(cc, lv, targetLocator.offset, true);
|
||||
CarpetSettings.LOG.error("dafuq");
|
||||
BlockState sourceBlockState = sourceLocator.block.getBlockState();
|
||||
CarpetSettings.LOG.error("finish dafuq");
|
||||
BlockState targetBlockState = world.getBlockState(targetLocator.block.getPos());
|
||||
CarpetSettings.LOG.error("finish dafuq 2");
|
||||
if (sourceLocator.offset < lv.size())
|
||||
{
|
||||
StateFactory<Block, BlockState> states = sourceBlockState.getBlock().getStateFactory();
|
||||
@@ -969,7 +965,6 @@ public class CarpetExpression
|
||||
sourceBlockState = setProperty(property, paramString, paramValue, sourceBlockState);
|
||||
}
|
||||
}
|
||||
CarpetSettings.LOG.error("finish properties got");
|
||||
|
||||
CompoundTag data = sourceLocator.block.getData();
|
||||
|
||||
@@ -3011,6 +3006,17 @@ public class CarpetExpression
|
||||
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) ->
|
||||
{
|
||||
Value res = lv.get(0).evalValue(c);
|
||||
|
||||
@@ -11,7 +11,13 @@ import carpet.script.Fluff.QuadFunction;
|
||||
import carpet.script.Fluff.QuinnFunction;
|
||||
import carpet.script.Fluff.SexFunction;
|
||||
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.ContainerValueInterface;
|
||||
import carpet.script.value.FunctionSignatureValue;
|
||||
@@ -3040,12 +3046,12 @@ public class Expression implements Cloneable
|
||||
return ((ThreadValue) v).join();
|
||||
});
|
||||
|
||||
addUnaryFunction("stop_task", (v) -> {
|
||||
/*addUnaryFunction("stop_task", (v) -> {
|
||||
if (!(v instanceof ThreadValue))
|
||||
throw new InternalExpressionException("'join_task' could only be used with a task value");
|
||||
((ThreadValue) v).stop();
|
||||
return Value.NULL;
|
||||
});
|
||||
});*/
|
||||
|
||||
addUnaryFunction("is_task_completed", (v) -> {
|
||||
if (!(v instanceof ThreadValue))
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package carpet.script.value;
|
||||
|
||||
import carpet.CarpetSettings;
|
||||
import carpet.script.Context;
|
||||
import carpet.script.Expression;
|
||||
import carpet.script.Tokenizer;
|
||||
@@ -10,46 +9,27 @@ import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class ThreadValue extends Value
|
||||
{
|
||||
private CompletableFuture<Value> taskFuture;
|
||||
//public static ThreadLocal<Boolean> joining = ThreadLocal.withInitial(() -> false);
|
||||
public final static Map<Thread,Integer> waitingTreads = new ConcurrentHashMap<>();
|
||||
public static Map<Thread,Integer> joinRequestedThreads = new ConcurrentHashMap<>();
|
||||
private long id;
|
||||
private final Object lock;
|
||||
//private final boolean[] started;
|
||||
private Thread executingThread;
|
||||
private Supplier<Value>task;
|
||||
private static long sequence = 0L;
|
||||
|
||||
private static final Map<Value,ThreadPoolExecutor> executorServices = new HashMap<>();
|
||||
|
||||
public ThreadValue(Value pool, FunctionValue function, Expression expr, Tokenizer.Token token, Context ctx)
|
||||
{
|
||||
id = sequence++;
|
||||
lock = new Object();
|
||||
executingThread = null;
|
||||
//started = new boolean[]{false};
|
||||
task = () ->
|
||||
{
|
||||
if (executingThread == null)
|
||||
{
|
||||
CarpetSettings.LOG.error("Setting the thread");
|
||||
executingThread = Thread.currentThread();
|
||||
return function.lazyEval(ctx, Context.NONE, expr, token, Collections.emptyList()).evalValue(ctx);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
taskFuture = CompletableFuture.supplyAsync(
|
||||
() -> { synchronized (lock) { CarpetSettings.LOG.error("getting in future"); Value ret = task.get(); CarpetSettings.LOG.error("gotten in future"); return ret;} },
|
||||
executorServices.computeIfAbsent(pool, (v) -> (ThreadPoolExecutor)Executors.newCachedThreadPool())
|
||||
() -> { synchronized (lock) {
|
||||
return function.lazyEval(ctx, Context.NONE, expr, token, Collections.emptyList()).evalValue(ctx);
|
||||
} },
|
||||
executorServices.computeIfAbsent(pool, (v) -> (ThreadPoolExecutor)Executors.newCachedThreadPool())
|
||||
);
|
||||
Thread.yield();
|
||||
}
|
||||
@@ -68,45 +48,14 @@ public class ThreadValue extends Value
|
||||
|
||||
public Value join()
|
||||
{
|
||||
CarpetSettings.LOG.error("in join "+id);
|
||||
if (executingThread == null)
|
||||
{
|
||||
CarpetSettings.LOG.error("not started "+id);
|
||||
Value res;
|
||||
waitingTreads.put(Thread.currentThread(), 1);
|
||||
try
|
||||
{
|
||||
CarpetSettings.LOG.error(" getting result "+id);
|
||||
res = task.get();
|
||||
CarpetSettings.LOG.error(" result got "+id);
|
||||
}
|
||||
finally
|
||||
{
|
||||
waitingTreads.remove(Thread.currentThread());
|
||||
}
|
||||
taskFuture.complete(res);
|
||||
return res;
|
||||
}
|
||||
try
|
||||
{
|
||||
synchronized (waitingTreads)
|
||||
{
|
||||
if (waitingTreads.containsKey(executingThread))
|
||||
throw new InternalExpressionException("Cannot wait/join on world accessing thread");
|
||||
waitingTreads.put(executingThread, 1);
|
||||
}
|
||||
CarpetSettings.LOG.error("getting future "+id);
|
||||
return taskFuture.get();
|
||||
}
|
||||
catch (InterruptedException | ExecutionException e)
|
||||
{
|
||||
return Value.NULL;
|
||||
}
|
||||
finally
|
||||
{
|
||||
waitingTreads.remove(executingThread);
|
||||
CarpetSettings.LOG.error(" future gotten "+id);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isFinished()
|
||||
@@ -120,7 +69,6 @@ public class ThreadValue extends Value
|
||||
{
|
||||
if (!taskFuture.isDone())
|
||||
{
|
||||
executingThread = Thread.currentThread();
|
||||
taskFuture.complete(Value.NULL);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user