threading testing

This commit is contained in:
gnembon committed 2019-12-17 10:28:14 -04:00
1 parent 5d32213922
commit 9ba573afe6
4 files changed
+86 -14

No files matched your search

@@ -0,0 +1,39 @@
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;
}
}
@@ -944,14 +944,18 @@ public class CarpetExpression
this.expr.addLazyFunction("set", -1, (c, t, lv) -> this.expr.addLazyFunction("set", -1, (c, t, lv) ->
{ {
CarpetSettings.LOG.error("starting");
CarpetContext cc = (CarpetContext)c; CarpetContext cc = (CarpetContext)c;
ServerWorld world = cc.s.getWorld(); ServerWorld world = cc.s.getWorld();
if (lv.size() < 2 || lv.size() % 2 == 1) if (lv.size() < 2 || lv.size() % 2 == 1)
throw new InternalExpressionException("'set' should have at least 2 params and odd attributes"); throw new InternalExpressionException("'set' should have at least 2 params and odd attributes");
BlockValue.LocatorResult targetLocator = BlockValue.fromParams(cc, lv, 0); BlockValue.LocatorResult targetLocator = BlockValue.fromParams(cc, lv, 0);
BlockValue.LocatorResult sourceLocator = BlockValue.fromParams(cc, lv, targetLocator.offset, true); BlockValue.LocatorResult sourceLocator = BlockValue.fromParams(cc, lv, targetLocator.offset, true);
CarpetSettings.LOG.error("dafuq");
BlockState sourceBlockState = sourceLocator.block.getBlockState(); BlockState sourceBlockState = sourceLocator.block.getBlockState();
CarpetSettings.LOG.error("finish dafuq");
BlockState targetBlockState = world.getBlockState(targetLocator.block.getPos()); BlockState targetBlockState = world.getBlockState(targetLocator.block.getPos());
CarpetSettings.LOG.error("finish dafuq 2");
if (sourceLocator.offset < lv.size()) if (sourceLocator.offset < lv.size())
{ {
StateFactory<Block, BlockState> states = sourceBlockState.getBlock().getStateFactory(); StateFactory<Block, BlockState> states = sourceBlockState.getBlock().getStateFactory();
@@ -965,6 +969,7 @@ public class CarpetExpression
sourceBlockState = setProperty(property, paramString, paramValue, sourceBlockState); sourceBlockState = setProperty(property, paramString, paramValue, sourceBlockState);
} }
} }
CarpetSettings.LOG.error("finish properties got");
CompoundTag data = sourceLocator.block.getData(); CompoundTag data = sourceLocator.block.getData();
@@ -1,5 +1,6 @@
package carpet.script.value; package carpet.script.value;
import carpet.CarpetSettings;
import carpet.script.Context; import carpet.script.Context;
import carpet.script.Expression; import carpet.script.Expression;
import carpet.script.Tokenizer; import carpet.script.Tokenizer;
@@ -9,6 +10,7 @@ import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
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;
@@ -17,9 +19,13 @@ import java.util.function.Supplier;
public class ThreadValue extends Value public class ThreadValue extends Value
{ {
private CompletableFuture<Value> taskFuture; 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 long id;
private final Object lock; private final Object lock;
private final boolean[] started; //private final boolean[] started;
private Thread executingThread;
private Supplier<Value>task; private Supplier<Value>task;
private static long sequence = 0L; private static long sequence = 0L;
@@ -29,18 +35,20 @@ public class ThreadValue extends Value
{ {
id = sequence++; id = sequence++;
lock = new Object(); lock = new Object();
started = new boolean[]{false}; executingThread = null;
//started = new boolean[]{false};
task = () -> task = () ->
{ {
if (!started[0]) if (executingThread == null)
{ {
started[0] = true; CarpetSettings.LOG.error("Setting the thread");
executingThread = Thread.currentThread();
return function.lazyEval(ctx, Context.NONE, expr, token, Collections.emptyList()).evalValue(ctx); return function.lazyEval(ctx, Context.NONE, expr, token, Collections.emptyList()).evalValue(ctx);
} }
return null; return null;
}; };
taskFuture = CompletableFuture.supplyAsync( taskFuture = CompletableFuture.supplyAsync(
() -> { synchronized (lock) { return task.get(); } }, () -> { 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()) executorServices.computeIfAbsent(pool, (v) -> (ThreadPoolExecutor)Executors.newCachedThreadPool())
); );
Thread.yield(); Thread.yield();
@@ -60,26 +68,45 @@ public class ThreadValue extends Value
public Value join() public Value join()
{ {
if (!started[0]) CarpetSettings.LOG.error("in join "+id);
if (executingThread == null)
{ {
synchronized (lock) CarpetSettings.LOG.error("not started "+id);
Value res;
waitingTreads.put(Thread.currentThread(), 1);
try
{ {
if (!started[0]) CarpetSettings.LOG.error(" getting result "+id);
{ res = task.get();
Value res = task.get(); CarpetSettings.LOG.error(" result got "+id);
taskFuture.complete(res);
return res;
}
} }
finally
{
waitingTreads.remove(Thread.currentThread());
}
taskFuture.complete(res);
return res;
} }
try 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(); return taskFuture.get();
} }
catch (InterruptedException | ExecutionException e) catch (InterruptedException | ExecutionException e)
{ {
return Value.NULL; return Value.NULL;
} }
finally
{
waitingTreads.remove(executingThread);
CarpetSettings.LOG.error(" future gotten "+id);
}
} }
public boolean isFinished() public boolean isFinished()
@@ -93,7 +120,7 @@ public class ThreadValue extends Value
{ {
if (!taskFuture.isDone()) if (!taskFuture.isDone())
{ {
started[0] = true; executingThread = Thread.currentThread();
taskFuture.complete(Value.NULL); taskFuture.complete(Value.NULL);
} }
} }
+1
View File
@@ -143,6 +143,7 @@
"FallingBlockEntity_scarpetEventsMixin", "FallingBlockEntity_scarpetEventsMixin",
"ChunkTicketManager_scarpetMixin", "ChunkTicketManager_scarpetMixin",
"ServerChunkManager_scarpetMixin", "ServerChunkManager_scarpetMixin",
"ServerChunkManager_scarpetThreadingProtectionMixin",
"PistonBlock_movableTEMixin", "PistonBlock_movableTEMixin",