threading testing
This commit is contained in:
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -143,6 +143,7 @@
|
|||||||
"FallingBlockEntity_scarpetEventsMixin",
|
"FallingBlockEntity_scarpetEventsMixin",
|
||||||
"ChunkTicketManager_scarpetMixin",
|
"ChunkTicketManager_scarpetMixin",
|
||||||
"ServerChunkManager_scarpetMixin",
|
"ServerChunkManager_scarpetMixin",
|
||||||
|
"ServerChunkManager_scarpetThreadingProtectionMixin",
|
||||||
|
|
||||||
|
|
||||||
"PistonBlock_movableTEMixin",
|
"PistonBlock_movableTEMixin",
|
||||||
|
|||||||
Reference in new issue
Block a user