Add thread safe relative features
This commit is contained in:
@@ -133,6 +133,11 @@
|
|||||||
<artifactId>mixin</artifactId>
|
<artifactId>mixin</artifactId>
|
||||||
<version>0.7.8-SNAPSHOT</version>
|
<version>0.7.8-SNAPSHOT</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>me.nallar.whocalled</groupId>
|
||||||
|
<artifactId>WhoCalled</artifactId>
|
||||||
|
<version>1.1</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<repositories>
|
<repositories>
|
||||||
@@ -148,6 +153,10 @@
|
|||||||
<id>spongepowered-repo</id>
|
<id>spongepowered-repo</id>
|
||||||
<url>https://repo.spongepowered.org/maven/</url>
|
<url>https://repo.spongepowered.org/maven/</url>
|
||||||
</repository>
|
</repository>
|
||||||
|
<repository>
|
||||||
|
<id>nallar-repo</id>
|
||||||
|
<url>http://repo.nallar.me/</url>
|
||||||
|
</repository>
|
||||||
</repositories>
|
</repositories>
|
||||||
|
|
||||||
<pluginRepositories>
|
<pluginRepositories>
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
package co.aikar.timings;
|
package co.aikar.timings;
|
||||||
|
|
||||||
import co.aikar.util.LoadingIntMap;
|
import co.aikar.util.LoadingIntMap;
|
||||||
|
import io.akarin.api.Akari;
|
||||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
|
|
||||||
|
|||||||
@@ -8,12 +8,14 @@ import java.util.concurrent.Executors;
|
|||||||
import java.util.concurrent.ThreadFactory;
|
import java.util.concurrent.ThreadFactory;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import org.bukkit.entity.Minecart;
|
||||||
|
|
||||||
import com.google.common.collect.Queues;
|
import com.google.common.collect.Queues;
|
||||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||||
|
|
||||||
import co.aikar.timings.Timing;
|
import co.aikar.timings.Timing;
|
||||||
import co.aikar.timings.Timings;
|
import co.aikar.timings.Timings;
|
||||||
|
import net.minecraft.server.MinecraftServer;
|
||||||
|
|
||||||
public abstract class Akari {
|
public abstract class Akari {
|
||||||
/**
|
/**
|
||||||
@@ -41,6 +43,12 @@ public abstract class Akari {
|
|||||||
*/
|
*/
|
||||||
public static final ExecutorCompletionService<?> STAGE_TICK = new ExecutorCompletionService<>(Executors.newSingleThreadExecutor(Akari.STAGE_FACTORY));
|
public static final ExecutorCompletionService<?> STAGE_TICK = new ExecutorCompletionService<>(Executors.newSingleThreadExecutor(Akari.STAGE_FACTORY));
|
||||||
|
|
||||||
|
public static volatile boolean mayMock;
|
||||||
|
|
||||||
|
public static boolean isPrimaryThread() {
|
||||||
|
return Thread.currentThread().equals(MinecraftServer.getServer().primaryThread);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The unsafe
|
* The unsafe
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -189,6 +189,26 @@ public class AkarinGlobalConfig {
|
|||||||
asyncLightingThreads = getInt("core.async-lighting.executor-threads", 2);
|
asyncLightingThreads = getInt("core.async-lighting.executor-threads", 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean enableMockPlugin;
|
||||||
|
private static void enableMockPlugin() {
|
||||||
|
enableMockPlugin = getBoolean("core.thread-safe.enable-mock-plugins", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<String> mockPackageList;
|
||||||
|
private static void mockPluginList() {
|
||||||
|
mockPackageList = getList("core.thread-safe.mock-package-name-contains", Lists.newArrayList());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean enableAsyncCatcher;
|
||||||
|
private static void enableAsyncCatcher() {
|
||||||
|
enableAsyncCatcher = getBoolean("core.thread-safe.async-catcher.enable", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean throwOnAsyncCaught;
|
||||||
|
private static void throwOnAsyncCaught() {
|
||||||
|
throwOnAsyncCaught = getBoolean("core.thread-safe.async-catcher.throw-on-caught", true);
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean asyncLightingWorkStealing;
|
public static boolean asyncLightingWorkStealing;
|
||||||
private static void asyncLightingWorkStealing() {
|
private static void asyncLightingWorkStealing() {
|
||||||
asyncLightingWorkStealing = getBoolean("core.async-lighting.use-work-stealing", false);
|
asyncLightingWorkStealing = getBoolean("core.async-lighting.use-work-stealing", false);
|
||||||
|
|||||||
@@ -7,9 +7,14 @@ import org.spongepowered.asm.mixin.Mutable;
|
|||||||
import org.spongepowered.asm.mixin.Overwrite;
|
import org.spongepowered.asm.mixin.Overwrite;
|
||||||
import org.spongepowered.asm.mixin.Shadow;
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
|
|
||||||
|
import io.akarin.server.core.AkarinGlobalConfig;
|
||||||
|
import me.nallar.whocalled.WhoCalled;
|
||||||
|
import net.minecraft.server.MinecraftServer;
|
||||||
|
|
||||||
@Mixin(value = CraftServer.class, remap = false)
|
@Mixin(value = CraftServer.class, remap = false)
|
||||||
public class MixinCraftServer {
|
public class MixinCraftServer {
|
||||||
@Shadow @Final @Mutable private String serverName;
|
@Shadow @Final @Mutable private String serverName;
|
||||||
|
@Shadow @Final protected MinecraftServer console;
|
||||||
private boolean needApplyServerName = true;
|
private boolean needApplyServerName = true;
|
||||||
|
|
||||||
@Overwrite
|
@Overwrite
|
||||||
@@ -22,4 +27,18 @@ public class MixinCraftServer {
|
|||||||
}
|
}
|
||||||
return serverName;
|
return serverName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Overwrite
|
||||||
|
public boolean isPrimaryThread() {
|
||||||
|
if (AkarinGlobalConfig.enableMockPlugin) {
|
||||||
|
// Mock forcely main thread plugins
|
||||||
|
String callerPackage = WhoCalled.$.getCallingClass().getPackage().getName();
|
||||||
|
if (callerPackage.startsWith("net.minecraft") || callerPackage.startsWith("org.bukkit") ||
|
||||||
|
callerPackage.startsWith("co.aikar") || callerPackage.startsWith("io.akarin")) return Thread.currentThread().equals(console.primaryThread);
|
||||||
|
for (String contains : AkarinGlobalConfig.mockPackageList) {
|
||||||
|
if (callerPackage.contains(contains)) return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Thread.currentThread().equals(console.primaryThread);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ public class MixinTimingHandler {
|
|||||||
|
|
||||||
@Overwrite
|
@Overwrite
|
||||||
public void stopTimingIfSync() {
|
public void stopTimingIfSync() {
|
||||||
if (Bukkit.isPrimaryThread()) {
|
if (Akari.isPrimaryThread()) { // Akarin
|
||||||
stopTiming(true); // Avoid twice thread check
|
stopTiming(true); // Avoid twice thread check
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -38,7 +38,7 @@ public class MixinTimingHandler {
|
|||||||
start = 0;
|
start = 0;
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
if (!sync && !Bukkit.isPrimaryThread()) {
|
if (!sync && !Akari.isPrimaryThread()) { // Akarin
|
||||||
if (AkarinGlobalConfig.silentAsyncTimings) {
|
if (AkarinGlobalConfig.silentAsyncTimings) {
|
||||||
Bukkit.getLogger().log(Level.SEVERE, "stopTiming called async for " + name);
|
Bukkit.getLogger().log(Level.SEVERE, "stopTiming called async for " + name);
|
||||||
new Throwable().printStackTrace();
|
new Throwable().printStackTrace();
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
|||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
|
import io.akarin.api.Akari;
|
||||||
import io.akarin.api.mixin.IMixinChunk;
|
import io.akarin.api.mixin.IMixinChunk;
|
||||||
import io.akarin.api.mixin.IMixinWorldServer;
|
import io.akarin.api.mixin.IMixinWorldServer;
|
||||||
import net.minecraft.server.BlockPosition;
|
import net.minecraft.server.BlockPosition;
|
||||||
@@ -245,7 +246,7 @@ public abstract class MixinChunk implements IMixinChunk {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Bukkit.isPrimaryThread()) {
|
if (Akari.isPrimaryThread()) { // Akarin
|
||||||
try {
|
try {
|
||||||
this.lightExecutorService.execute(() -> {
|
this.lightExecutorService.execute(() -> {
|
||||||
this.checkLightAsync(neighborChunks);
|
this.checkLightAsync(neighborChunks);
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ import org.bukkit.Bukkit;
|
|||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||||
|
|
||||||
|
import io.akarin.api.Akari;
|
||||||
import io.akarin.api.mixin.IMixinChunk;
|
import io.akarin.api.mixin.IMixinChunk;
|
||||||
import io.akarin.api.mixin.IMixinWorldServer;
|
import io.akarin.api.mixin.IMixinWorldServer;
|
||||||
import io.akarin.server.core.AkarinGlobalConfig;
|
import io.akarin.server.core.AkarinGlobalConfig;
|
||||||
@@ -240,7 +241,7 @@ public abstract class MixinWorldServer extends MixinWorld implements IMixinWorld
|
|||||||
neighbor.setLightUpdateTime(chunk.getWorld().getTime());
|
neighbor.setLightUpdateTime(chunk.getWorld().getTime());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Bukkit.isPrimaryThread()) {
|
if (Akari.isPrimaryThread()) { // Akarin
|
||||||
this.lightExecutorService.execute(() -> {
|
this.lightExecutorService.execute(() -> {
|
||||||
this.checkLightAsync(lightType, pos, chunk, neighbors);
|
this.checkLightAsync(lightType, pos, chunk, neighbors);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package net.minecraft.server;
|
|||||||
import com.google.common.primitives.Doubles;
|
import com.google.common.primitives.Doubles;
|
||||||
import com.google.common.primitives.Floats;
|
import com.google.common.primitives.Floats;
|
||||||
|
|
||||||
|
import io.akarin.api.Akari;
|
||||||
import io.akarin.server.core.AkarinGlobalConfig;
|
import io.akarin.server.core.AkarinGlobalConfig;
|
||||||
import io.netty.util.concurrent.Future;
|
import io.netty.util.concurrent.Future;
|
||||||
import io.netty.util.concurrent.GenericFutureListener;
|
import io.netty.util.concurrent.GenericFutureListener;
|
||||||
@@ -1384,7 +1385,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable {
|
|||||||
|
|
||||||
if (!async && s.startsWith("/")) {
|
if (!async && s.startsWith("/")) {
|
||||||
// Paper Start
|
// Paper Start
|
||||||
if (!org.spigotmc.AsyncCatcher.shuttingDown && !org.bukkit.Bukkit.isPrimaryThread()) {
|
if (!org.spigotmc.AsyncCatcher.shuttingDown && !Akari.isPrimaryThread()) { // Akarin
|
||||||
final String fCommandLine = s;
|
final String fCommandLine = s;
|
||||||
MinecraftServer.LOGGER.log(org.apache.logging.log4j.Level.ERROR, "Command Dispatched Async: " + fCommandLine);
|
MinecraftServer.LOGGER.log(org.apache.logging.log4j.Level.ERROR, "Command Dispatched Async: " + fCommandLine);
|
||||||
MinecraftServer.LOGGER.log(org.apache.logging.log4j.Level.ERROR, "Please notify author of plugin causing this execution to fix this bug! see: http://bit.ly/1oSiM6C", new Throwable());
|
MinecraftServer.LOGGER.log(org.apache.logging.log4j.Level.ERROR, "Please notify author of plugin causing this execution to fix this bug! see: http://bit.ly/1oSiM6C", new Throwable());
|
||||||
|
|||||||
Reference in New Issue
Block a user