Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: vastly superier handling of queue chunks #2461

Merged
merged 3 commits into from
Oct 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,11 @@
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Future;
import java.util.concurrent.Semaphore;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.function.Function;
import java.util.stream.Collectors;
Expand All @@ -91,22 +93,24 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
.getInstance()
.getBukkitImplAdapter());
private final ReadWriteLock sectionLock = new ReentrantReadWriteLock();
private final ReentrantLock callLock = new ReentrantLock();
private final ServerLevel serverLevel;
private final int chunkX;
private final int chunkZ;
private final int minHeight;
private final int maxHeight;
private final int minSectionPosition;
private final int maxSectionPosition;
private final ConcurrentHashMap<Integer, PaperweightGetBlocks_Copy> copies = new ConcurrentHashMap<>();
private final Object sendLock = new Object();
private LevelChunkSection[] sections;
private LevelChunk levelChunk;
private DataLayer[] blockLight;
private DataLayer[] skyLight;
private boolean createCopy = false;
private PaperweightGetBlocks_Copy copy = null;
private boolean forceLoadSections = true;
private boolean lightUpdate = false;
private int copyKey = 0;

public PaperweightGetBlocks(World world, int chunkX, int chunkZ) {
this(((CraftWorld) world).getHandle(), chunkX, chunkZ);
Expand Down Expand Up @@ -139,13 +143,27 @@ public boolean isCreateCopy() {
}

@Override
public void setCreateCopy(boolean createCopy) {
public int setCreateCopy(boolean createCopy) {
if (!callLock.isHeldByCurrentThread()) {
throw new IllegalStateException("Attempting to set if chunk GET should create copy, but it is not call-locked.");
}
this.createCopy = createCopy;
return ++this.copyKey;
}

@Override
public IChunkGet getCopy(final int key) {
return copies.remove(key);
}

@Override
public void lockCall() {
this.callLock.lock();
}

@Override
public IChunkGet getCopy() {
return copy;
public void unlockCall() {
this.callLock.unlock();
}

@Override
Expand Down Expand Up @@ -394,8 +412,17 @@ public LevelChunk ensureLoaded(ServerLevel nmsWorld, int chunkX, int chunkZ) {
@Override
@SuppressWarnings("rawtypes")
public synchronized <T extends Future<T>> T call(IChunkSet set, Runnable finalizer) {
if (!callLock.isHeldByCurrentThread()) {
throw new IllegalStateException("Attempted to call chunk GET but chunk was not call-locked.");
}
forceLoadSections = false;
copy = createCopy ? new PaperweightGetBlocks_Copy(getChunk()) : null;
PaperweightGetBlocks_Copy copy = createCopy ? new PaperweightGetBlocks_Copy(levelChunk) : null;
if (createCopy) {
if (copies.containsKey(copyKey)) {
throw new IllegalStateException("Copy key already used.");
}
copies.put(copyKey, copy);
}
try {
ServerLevel nmsWorld = serverLevel;
LevelChunk nmsChunk = ensureLoaded(nmsWorld, chunkX, chunkZ);
Expand Down Expand Up @@ -832,9 +859,7 @@ private char[] loadPrivately(int layer) {
if (super.sections[layer] != null) {
synchronized (super.sectionLocks[layer]) {
if (super.sections[layer].isFull() && super.blocks[layer] != null) {
char[] blocks = new char[4096];
System.arraycopy(super.blocks[layer], 0, blocks, 0, 4096);
return blocks;
return super.blocks[layer];
}
}
}
Expand Down Expand Up @@ -949,9 +974,7 @@ private char ordinal(net.minecraft.world.level.block.state.BlockState ibd, Paper

public LevelChunkSection[] getSections(boolean force) {
force &= forceLoadSections;
sectionLock.readLock().lock();
LevelChunkSection[] tmp = sections;
sectionLock.readLock().unlock();
if (tmp == null || force) {
try {
sectionLock.writeLock().lock();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import net.minecraft.world.level.chunk.LevelChunk;

import javax.annotation.Nullable;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
Expand Down Expand Up @@ -99,7 +100,8 @@ public boolean isCreateCopy() {
}

@Override
public void setCreateCopy(boolean createCopy) {
public int setCreateCopy(boolean createCopy) {
return -1;
}

@Override
Expand Down Expand Up @@ -196,6 +198,10 @@ public boolean hasSection(int layer) {
@Override
public char[] load(int layer) {
layer -= getMinSectionPosition();
if (blocks[layer] == null) {
blocks[layer] = new char[4096];
Arrays.fill(blocks[layer], (char) BlockTypesCache.ReservedIDs.AIR);
}
return blocks[layer];
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
import com.fastasyncworldedit.core.util.MathMan;
import com.fastasyncworldedit.core.util.collection.AdaptedMap;
import com.google.common.base.Suppliers;
import com.google.common.collect.Iterables;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.ListTag;
import com.sk89q.jnbt.StringTag;
Expand Down Expand Up @@ -66,7 +65,6 @@
import java.util.AbstractSet;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
Expand All @@ -76,13 +74,14 @@
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Future;
import java.util.concurrent.Semaphore;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;

public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBlocks {

Expand All @@ -95,6 +94,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
.getInstance()
.getBukkitImplAdapter());
private final ReadWriteLock sectionLock = new ReentrantReadWriteLock();
private final ReentrantLock callLock = new ReentrantLock();
private final ServerLevel serverLevel;
private final int chunkX;
private final int chunkZ;
Expand All @@ -104,15 +104,16 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
private final int maxSectionPosition;
private final Registry<Biome> biomeRegistry;
private final IdMap<Holder<Biome>> biomeHolderIdMap;
private final ConcurrentHashMap<Integer, PaperweightGetBlocks_Copy> copies = new ConcurrentHashMap<>();
private final Object sendLock = new Object();
private LevelChunkSection[] sections;
private LevelChunk levelChunk;
private DataLayer[] blockLight;
private DataLayer[] skyLight;
private boolean createCopy = false;
private PaperweightGetBlocks_Copy copy = null;
private boolean forceLoadSections = true;
private boolean lightUpdate = false;
private int copyKey = 0;

public PaperweightGetBlocks(World world, int chunkX, int chunkZ) {
this(((CraftWorld) world).getHandle(), chunkX, chunkZ);
Expand Down Expand Up @@ -147,13 +148,27 @@ public boolean isCreateCopy() {
}

@Override
public void setCreateCopy(boolean createCopy) {
public int setCreateCopy(boolean createCopy) {
if (!callLock.isHeldByCurrentThread()) {
throw new IllegalStateException("Attempting to set if chunk GET should create copy, but it is not call-locked.");
}
this.createCopy = createCopy;
return ++this.copyKey;
}

@Override
public IChunkGet getCopy(final int key) {
return copies.remove(key);
}

@Override
public void lockCall() {
this.callLock.lock();
}

@Override
public IChunkGet getCopy() {
return copy;
public void unlockCall() {
this.callLock.unlock();
}

@Override
Expand Down Expand Up @@ -388,8 +403,17 @@ public LevelChunk ensureLoaded(ServerLevel nmsWorld, int chunkX, int chunkZ) {
@Override
@SuppressWarnings("rawtypes")
public synchronized <T extends Future<T>> T call(IChunkSet set, Runnable finalizer) {
if (!callLock.isHeldByCurrentThread()) {
throw new IllegalStateException("Attempted to call chunk GET but chunk was not call-locked.");
}
forceLoadSections = false;
copy = createCopy ? new PaperweightGetBlocks_Copy(getChunk()) : null;
PaperweightGetBlocks_Copy copy = createCopy ? new PaperweightGetBlocks_Copy(levelChunk) : null;
if (createCopy) {
if (copies.containsKey(copyKey)) {
throw new IllegalStateException("Copy key already used.");
}
copies.put(copyKey, copy);
}
try {
ServerLevel nmsWorld = serverLevel;
LevelChunk nmsChunk = ensureLoaded(nmsWorld, chunkX, chunkZ);
Expand Down Expand Up @@ -883,9 +907,7 @@ private char[] loadPrivately(int layer) {
if (super.sections[layer] != null) {
synchronized (super.sectionLocks[layer]) {
if (super.sections[layer].isFull() && super.blocks[layer] != null) {
char[] blocks = new char[4096];
System.arraycopy(super.blocks[layer], 0, blocks, 0, 4096);
return blocks;
return super.blocks[layer];
}
}
}
Expand Down Expand Up @@ -1007,9 +1029,7 @@ private char ordinal(BlockState ibd, PaperweightFaweAdapter adapter) {

public LevelChunkSection[] getSections(boolean force) {
force &= forceLoadSections;
sectionLock.readLock().lock();
LevelChunkSection[] tmp = sections;
sectionLock.readLock().unlock();
if (tmp == null || force) {
try {
sectionLock.writeLock().lock();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2.nbt.PaperweightLazyCompoundTag;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.biome.BiomeTypes;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockTypesCache;
Expand All @@ -24,6 +23,7 @@
import net.minecraft.world.level.chunk.PalettedContainer;

import javax.annotation.Nullable;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
Expand Down Expand Up @@ -101,7 +101,8 @@ public boolean isCreateCopy() {
}

@Override
public void setCreateCopy(boolean createCopy) {
public int setCreateCopy(boolean createCopy) {
return -1;
}

@Override
Expand Down Expand Up @@ -187,6 +188,10 @@ public boolean hasSection(int layer) {
@Override
public char[] load(int layer) {
layer -= getMinSectionPosition();
if (blocks[layer] == null) {
blocks[layer] = new char[4096];
Arrays.fill(blocks[layer], (char) BlockTypesCache.ReservedIDs.AIR);
}
return blocks[layer];
}

Expand Down
Loading
Loading