mirror of
https://github.com/plexusorg/Plex-FAWE.git
synced 2024-12-23 01:37:37 +00:00
Avoid Unsafe on paper (#1678)
This commit is contained in:
parent
d1588f9207
commit
c45b14a52d
@ -1,7 +1,6 @@
|
|||||||
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_17_R1_2;
|
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_17_R1_2;
|
||||||
|
|
||||||
import com.fastasyncworldedit.bukkit.adapter.BukkitGetBlocks;
|
import com.fastasyncworldedit.bukkit.adapter.BukkitGetBlocks;
|
||||||
import com.fastasyncworldedit.bukkit.adapter.DelegateSemaphore;
|
|
||||||
import com.fastasyncworldedit.core.Fawe;
|
import com.fastasyncworldedit.core.Fawe;
|
||||||
import com.fastasyncworldedit.core.FaweCache;
|
import com.fastasyncworldedit.core.FaweCache;
|
||||||
import com.fastasyncworldedit.core.configuration.Settings;
|
import com.fastasyncworldedit.core.configuration.Settings;
|
||||||
@ -74,6 +73,7 @@ import java.util.Set;
|
|||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
|
import java.util.concurrent.Semaphore;
|
||||||
import java.util.concurrent.locks.ReadWriteLock;
|
import java.util.concurrent.locks.ReadWriteLock;
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
@ -505,7 +505,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
}
|
}
|
||||||
|
|
||||||
//ensure that the server doesn't try to tick the chunksection while we're editing it (again).
|
//ensure that the server doesn't try to tick the chunksection while we're editing it (again).
|
||||||
DelegateSemaphore lock = PaperweightPlatformAdapter.applyLock(existingSection);
|
Semaphore lock = PaperweightPlatformAdapter.applyLock(existingSection);
|
||||||
PaperweightPlatformAdapter.clearCounts(existingSection);
|
PaperweightPlatformAdapter.clearCounts(existingSection);
|
||||||
if (PaperLib.isPaper()) {
|
if (PaperLib.isPaper()) {
|
||||||
existingSection.tickingList.clear();
|
existingSection.tickingList.clear();
|
||||||
@ -867,7 +867,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
data = new char[4096];
|
data = new char[4096];
|
||||||
Arrays.fill(data, (char) BlockTypesCache.ReservedIDs.AIR);
|
Arrays.fill(data, (char) BlockTypesCache.ReservedIDs.AIR);
|
||||||
}
|
}
|
||||||
DelegateSemaphore lock = PaperweightPlatformAdapter.applyLock(section);
|
Semaphore lock = PaperweightPlatformAdapter.applyLock(section);
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
// Efficiently convert ChunkSection to raw data
|
// Efficiently convert ChunkSection to raw data
|
||||||
try {
|
try {
|
||||||
|
@ -30,6 +30,7 @@ import net.minecraft.server.level.ChunkMap;
|
|||||||
import net.minecraft.server.level.ServerLevel;
|
import net.minecraft.server.level.ServerLevel;
|
||||||
import net.minecraft.server.level.ServerPlayer;
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
import net.minecraft.util.BitStorage;
|
import net.minecraft.util.BitStorage;
|
||||||
|
import net.minecraft.util.ThreadingDetector;
|
||||||
import net.minecraft.world.level.ChunkPos;
|
import net.minecraft.world.level.ChunkPos;
|
||||||
import net.minecraft.world.level.LevelAccessor;
|
import net.minecraft.world.level.LevelAccessor;
|
||||||
import net.minecraft.world.level.biome.Biome;
|
import net.minecraft.world.level.biome.Biome;
|
||||||
@ -117,8 +118,15 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
methodGetVisibleChunk = MethodHandles.lookup().unreflect(getVisibleChunkIfPresent);
|
methodGetVisibleChunk = MethodHandles.lookup().unreflect(getVisibleChunkIfPresent);
|
||||||
|
|
||||||
Unsafe unsafe = ReflectionUtils.getUnsafe();
|
Unsafe unsafe = ReflectionUtils.getUnsafe();
|
||||||
fieldLock = PalettedContainer.class.getDeclaredField(Refraction.pickName("lock", "m"));
|
if (!PaperLib.isPaper()) {
|
||||||
|
|
||||||
|
fieldLock = ThreadingDetector.class.getDeclaredField(Refraction.pickName("lock", "m"));
|
||||||
fieldLockOffset = unsafe.objectFieldOffset(fieldLock);
|
fieldLockOffset = unsafe.objectFieldOffset(fieldLock);
|
||||||
|
} else {
|
||||||
|
// in paper, the used methods are synchronized properly
|
||||||
|
fieldLock = null;
|
||||||
|
fieldLockOffset = -1;
|
||||||
|
}
|
||||||
|
|
||||||
fieldGameEventDispatcherSections = LevelChunk.class.getDeclaredField(Refraction.pickName(
|
fieldGameEventDispatcherSections = LevelChunk.class.getDeclaredField(Refraction.pickName(
|
||||||
"gameEventDispatcherSections", "x"));
|
"gameEventDispatcherSections", "x"));
|
||||||
@ -162,8 +170,12 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static DelegateSemaphore applyLock(LevelChunkSection section) {
|
private static final ThreadLocal<Semaphore> SEMAPHORE_THREAD_LOCAL = ThreadLocal.withInitial(() -> new Semaphore(1));
|
||||||
//todo there has to be a better way to do this. Maybe using a() in DataPaletteBlock which acquires the lock in NMS?
|
|
||||||
|
static Semaphore applyLock(LevelChunkSection section) {
|
||||||
|
if (PaperLib.isPaper()) {
|
||||||
|
return SEMAPHORE_THREAD_LOCAL.get();
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
synchronized (section) {
|
synchronized (section) {
|
||||||
Unsafe unsafe = ReflectionUtils.getUnsafe();
|
Unsafe unsafe = ReflectionUtils.getUnsafe();
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R1;
|
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R1;
|
||||||
|
|
||||||
import com.fastasyncworldedit.bukkit.adapter.BukkitGetBlocks;
|
import com.fastasyncworldedit.bukkit.adapter.BukkitGetBlocks;
|
||||||
import com.fastasyncworldedit.bukkit.adapter.DelegateSemaphore;
|
|
||||||
import com.fastasyncworldedit.core.Fawe;
|
import com.fastasyncworldedit.core.Fawe;
|
||||||
import com.fastasyncworldedit.core.FaweCache;
|
import com.fastasyncworldedit.core.FaweCache;
|
||||||
import com.fastasyncworldedit.core.configuration.Settings;
|
import com.fastasyncworldedit.core.configuration.Settings;
|
||||||
@ -75,6 +74,7 @@ import java.util.Set;
|
|||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
|
import java.util.concurrent.Semaphore;
|
||||||
import java.util.concurrent.locks.ReadWriteLock;
|
import java.util.concurrent.locks.ReadWriteLock;
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
@ -560,7 +560,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
if (PaperLib.isPaper()) {
|
if (PaperLib.isPaper()) {
|
||||||
existingSection.tickingList.clear();
|
existingSection.tickingList.clear();
|
||||||
}
|
}
|
||||||
DelegateSemaphore lock = PaperweightPlatformAdapter.applyLock(existingSection);
|
Semaphore lock = PaperweightPlatformAdapter.applyLock(existingSection);
|
||||||
|
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
// lock.acquire();
|
// lock.acquire();
|
||||||
@ -895,7 +895,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
data = new char[4096];
|
data = new char[4096];
|
||||||
Arrays.fill(data, (char) BlockTypesCache.ReservedIDs.AIR);
|
Arrays.fill(data, (char) BlockTypesCache.ReservedIDs.AIR);
|
||||||
}
|
}
|
||||||
DelegateSemaphore lock = PaperweightPlatformAdapter.applyLock(section);
|
Semaphore lock = PaperweightPlatformAdapter.applyLock(section);
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
// Efficiently convert ChunkSection to raw data
|
// Efficiently convert ChunkSection to raw data
|
||||||
try {
|
try {
|
||||||
|
@ -133,11 +133,20 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
methodGetVisibleChunk = MethodHandles.lookup().unreflect(getVisibleChunkIfPresent);
|
methodGetVisibleChunk = MethodHandles.lookup().unreflect(getVisibleChunkIfPresent);
|
||||||
|
|
||||||
Unsafe unsafe = ReflectionUtils.getUnsafe();
|
Unsafe unsafe = ReflectionUtils.getUnsafe();
|
||||||
|
if (!PaperLib.isPaper()) {
|
||||||
fieldThreadingDetector = PalettedContainer.class.getDeclaredField(Refraction.pickName("threadingDetector", "f"));
|
fieldThreadingDetector = PalettedContainer.class.getDeclaredField(Refraction.pickName("threadingDetector", "f"));
|
||||||
fieldThreadingDetectorOffset = unsafe.objectFieldOffset(fieldThreadingDetector);
|
fieldThreadingDetectorOffset = unsafe.objectFieldOffset(fieldThreadingDetector);
|
||||||
|
|
||||||
fieldLock = ThreadingDetector.class.getDeclaredField(Refraction.pickName("lock", "c"));
|
fieldLock = ThreadingDetector.class.getDeclaredField(Refraction.pickName("lock", "c"));
|
||||||
fieldLockOffset = unsafe.objectFieldOffset(fieldLock);
|
fieldLockOffset = unsafe.objectFieldOffset(fieldLock);
|
||||||
|
} else {
|
||||||
|
// in paper, the used methods are synchronized properly
|
||||||
|
fieldThreadingDetector = null;
|
||||||
|
fieldThreadingDetectorOffset = -1;
|
||||||
|
|
||||||
|
fieldLock = null;
|
||||||
|
fieldLockOffset = -1;
|
||||||
|
}
|
||||||
|
|
||||||
fieldGameEventDispatcherSections = LevelChunk.class.getDeclaredField(Refraction.pickName(
|
fieldGameEventDispatcherSections = LevelChunk.class.getDeclaredField(Refraction.pickName(
|
||||||
"gameEventDispatcherSections", "t"));
|
"gameEventDispatcherSections", "t"));
|
||||||
@ -181,7 +190,12 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static DelegateSemaphore applyLock(LevelChunkSection section) {
|
private static final ThreadLocal<Semaphore> SEMAPHORE_THREAD_LOCAL = ThreadLocal.withInitial(() -> new Semaphore(1));
|
||||||
|
|
||||||
|
static Semaphore applyLock(LevelChunkSection section) {
|
||||||
|
if (PaperLib.isPaper()) {
|
||||||
|
return SEMAPHORE_THREAD_LOCAL.get();
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
synchronized (section) {
|
synchronized (section) {
|
||||||
Unsafe unsafe = ReflectionUtils.getUnsafe();
|
Unsafe unsafe = ReflectionUtils.getUnsafe();
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2;
|
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2;
|
||||||
|
|
||||||
import com.fastasyncworldedit.bukkit.adapter.BukkitGetBlocks;
|
import com.fastasyncworldedit.bukkit.adapter.BukkitGetBlocks;
|
||||||
import com.fastasyncworldedit.bukkit.adapter.DelegateSemaphore;
|
|
||||||
import com.fastasyncworldedit.core.Fawe;
|
import com.fastasyncworldedit.core.Fawe;
|
||||||
import com.fastasyncworldedit.core.FaweCache;
|
import com.fastasyncworldedit.core.FaweCache;
|
||||||
import com.fastasyncworldedit.core.configuration.Settings;
|
import com.fastasyncworldedit.core.configuration.Settings;
|
||||||
@ -76,6 +75,7 @@ import java.util.Set;
|
|||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
|
import java.util.concurrent.Semaphore;
|
||||||
import java.util.concurrent.locks.ReadWriteLock;
|
import java.util.concurrent.locks.ReadWriteLock;
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
@ -576,7 +576,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
if (PaperLib.isPaper()) {
|
if (PaperLib.isPaper()) {
|
||||||
existingSection.tickingList.clear();
|
existingSection.tickingList.clear();
|
||||||
}
|
}
|
||||||
DelegateSemaphore lock = PaperweightPlatformAdapter.applyLock(existingSection);
|
Semaphore lock = PaperweightPlatformAdapter.applyLock(existingSection);
|
||||||
|
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
// lock.acquire();
|
// lock.acquire();
|
||||||
@ -914,7 +914,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
data = new char[4096];
|
data = new char[4096];
|
||||||
Arrays.fill(data, (char) BlockTypesCache.ReservedIDs.AIR);
|
Arrays.fill(data, (char) BlockTypesCache.ReservedIDs.AIR);
|
||||||
}
|
}
|
||||||
DelegateSemaphore lock = PaperweightPlatformAdapter.applyLock(section);
|
Semaphore lock = PaperweightPlatformAdapter.applyLock(section);
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
// Efficiently convert ChunkSection to raw data
|
// Efficiently convert ChunkSection to raw data
|
||||||
try {
|
try {
|
||||||
|
@ -132,11 +132,20 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
methodGetVisibleChunk = MethodHandles.lookup().unreflect(getVisibleChunkIfPresent);
|
methodGetVisibleChunk = MethodHandles.lookup().unreflect(getVisibleChunkIfPresent);
|
||||||
|
|
||||||
Unsafe unsafe = ReflectionUtils.getUnsafe();
|
Unsafe unsafe = ReflectionUtils.getUnsafe();
|
||||||
|
if (!PaperLib.isPaper()) {
|
||||||
fieldThreadingDetector = PalettedContainer.class.getDeclaredField(Refraction.pickName("threadingDetector", "f"));
|
fieldThreadingDetector = PalettedContainer.class.getDeclaredField(Refraction.pickName("threadingDetector", "f"));
|
||||||
fieldThreadingDetectorOffset = unsafe.objectFieldOffset(fieldThreadingDetector);
|
fieldThreadingDetectorOffset = unsafe.objectFieldOffset(fieldThreadingDetector);
|
||||||
|
|
||||||
fieldLock = ThreadingDetector.class.getDeclaredField(Refraction.pickName("lock", "c"));
|
fieldLock = ThreadingDetector.class.getDeclaredField(Refraction.pickName("lock", "c"));
|
||||||
fieldLockOffset = unsafe.objectFieldOffset(fieldLock);
|
fieldLockOffset = unsafe.objectFieldOffset(fieldLock);
|
||||||
|
} else {
|
||||||
|
// in paper, the used methods are synchronized properly
|
||||||
|
fieldThreadingDetector = null;
|
||||||
|
fieldThreadingDetectorOffset = -1;
|
||||||
|
|
||||||
|
fieldLock = null;
|
||||||
|
fieldLockOffset = -1;
|
||||||
|
}
|
||||||
|
|
||||||
fieldGameEventDispatcherSections = LevelChunk.class.getDeclaredField(Refraction.pickName(
|
fieldGameEventDispatcherSections = LevelChunk.class.getDeclaredField(Refraction.pickName(
|
||||||
"gameEventDispatcherSections", "t"));
|
"gameEventDispatcherSections", "t"));
|
||||||
@ -180,7 +189,12 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static DelegateSemaphore applyLock(LevelChunkSection section) {
|
private static final ThreadLocal<Semaphore> SEMAPHORE_THREAD_LOCAL = ThreadLocal.withInitial(() -> new Semaphore(1));
|
||||||
|
|
||||||
|
static Semaphore applyLock(LevelChunkSection section) {
|
||||||
|
if (PaperLib.isPaper()) {
|
||||||
|
return SEMAPHORE_THREAD_LOCAL.get();
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
synchronized (section) {
|
synchronized (section) {
|
||||||
Unsafe unsafe = ReflectionUtils.getUnsafe();
|
Unsafe unsafe = ReflectionUtils.getUnsafe();
|
||||||
@ -192,7 +206,7 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
synchronized (currentThreadingDetector) {
|
synchronized (currentThreadingDetector) {
|
||||||
Semaphore currentLock = (Semaphore) unsafe.getObject(currentThreadingDetector, fieldLockOffset);
|
Semaphore currentLock = (Semaphore) unsafe.getObject(currentThreadingDetector, fieldLockOffset);
|
||||||
if (currentLock instanceof DelegateSemaphore) {
|
if (currentLock instanceof DelegateSemaphore) {
|
||||||
return (DelegateSemaphore) currentLock;
|
return currentLock;
|
||||||
}
|
}
|
||||||
DelegateSemaphore newLock = new DelegateSemaphore(1, currentLock);
|
DelegateSemaphore newLock = new DelegateSemaphore(1, currentLock);
|
||||||
unsafe.putObject(currentThreadingDetector, fieldLockOffset, newLock);
|
unsafe.putObject(currentThreadingDetector, fieldLockOffset, newLock);
|
||||||
|
Loading…
Reference in New Issue
Block a user