Reuse get array after apply

This commit is contained in:
Jesse Boyd 2019-05-02 05:02:11 +10:00
parent 18e6c09fdd
commit 4619fd2b49
No known key found for this signature in database
GPG Key ID: 59F1DE6293AF6E1F
4 changed files with 71 additions and 21 deletions

View File

@ -28,6 +28,23 @@ public class BukkitChunkHolder<T extends Future<T>> extends ChunkHolder {
return new BukkitGetBlocks(extent.getNmsWorld(), getX(), getZ());
}
private void updateGet(BukkitGetBlocks get, Chunk nmsChunk, ChunkSection[] sections, ChunkSection section, char[] arr, int layer) {
synchronized (get) {
if (get.nmsChunk != nmsChunk) {
get.nmsChunk = nmsChunk;
get.sections = sections.clone();
get.reset();
}
if (get.sections == null) {
get.sections = sections;
}
if (get.sections[layer] != section) {
get.sections[layer] = section;
}
get.blocks[layer] = arr;
}
}
@Override
public T call() {
BukkitQueue extent = (BukkitQueue) getExtent();
@ -51,6 +68,7 @@ public class BukkitChunkHolder<T extends Future<T>> extends ChunkHolder {
if (existingSection == null) {
newSection = extent.newChunkSection(layer, hasSky, setArr);
if (BukkitQueue.setSectionAtomic(sections, null, newSection, layer)) {
updateGet(get, nmsChunk, sections, newSection, setArr, layer);
continue;
} else {
existingSection = sections[layer];
@ -62,10 +80,7 @@ public class BukkitChunkHolder<T extends Future<T>> extends ChunkHolder {
}
DelegateLock lock = BukkitQueue.applyLock(existingSection);
synchronized (lock) {
if (lock.isLocked()) {
lock.lock();
lock.unlock();
}
lock.untilFree();
synchronized (get) {
ChunkSection getSection;
if (get.nmsChunk != nmsChunk) {
@ -95,6 +110,8 @@ public class BukkitChunkHolder<T extends Future<T>> extends ChunkHolder {
if (!BukkitQueue.setSectionAtomic(sections, existingSection, newSection, layer)) {
System.out.println("Failed to set chunk section:" + X + "," + Z + " layer: " + layer);
continue;
} else {
updateGet(get, nmsChunk, sections, newSection, setArr, layer);
}
}
}

View File

@ -64,10 +64,7 @@ public class BukkitGetBlocks extends CharGetBlocks {
}
DelegateLock lock = BukkitQueue.applyLock(section);
synchronized (lock) {
if (lock.isLocked()) {
lock.lock();
lock.unlock();
}
lock.untilFree();
lock.setModified(false);
// Efficiently convert ChunkSection to raw data
try {

View File

@ -39,7 +39,9 @@ import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import sun.misc.Unsafe;
@ -135,6 +137,7 @@ public class BukkitQueue extends SimpleCharQueueExtent {
fieldLock = tmp;
fieldLock.setAccessible(true);
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
int modifiers = modifiersField.getInt(fieldLock);
int newModifiers = modifiers & (~Modifier.FINAL);
if (newModifiers != modifiers) modifiersField.setInt(fieldLock, newModifiers);
@ -154,7 +157,7 @@ public class BukkitQueue extends SimpleCharQueueExtent {
}
}
public static boolean setSectionAtomic(ChunkSection[] sections, ChunkSection expected, ChunkSection value, int layer) {
protected static boolean setSectionAtomic(ChunkSection[] sections, ChunkSection expected, ChunkSection value, int layer) {
long offset = ((long) layer << CHUNKSECTION_SHIFT) + CHUNKSECTION_BASE;
if (layer >= 0 && layer < sections.length) {
return UnsafeUtils.getUNSAFE().compareAndSwapObject(sections, offset, expected, value);
@ -162,11 +165,11 @@ public class BukkitQueue extends SimpleCharQueueExtent {
return false;
}
public static DelegateLock applyLock(ChunkSection section) {
protected static DelegateLock applyLock(ChunkSection section) {
try {
synchronized (section) {
DataPaletteBlock<IBlockData> blocks = section.getBlocks();
ReentrantLock currentLock = (ReentrantLock) fieldLock.get(blocks);
Lock currentLock = (Lock) fieldLock.get(blocks);
if (currentLock instanceof DelegateLock) {
return (DelegateLock) currentLock;
}

View File

@ -1,16 +1,27 @@
package com.boydti.fawe.bukkit.beta;
import org.apache.commons.lang.mutable.MutableInt;
import java.util.Collection;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.LongAdder;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class DelegateLock extends ReentrantLock {
private final ReentrantLock parent;
private final Lock parent;
private volatile boolean modified;
private final AtomicInteger count;
public DelegateLock(ReentrantLock parent) {
public DelegateLock(Lock parent) {
this.parent = parent;
if (!(parent instanceof ReentrantLock)) {
count = new AtomicInteger();
} else {
count = null;
}
}
public boolean isModified() {
@ -22,9 +33,12 @@ public class DelegateLock extends ReentrantLock {
}
@Override
public void lock() {
public synchronized void lock() {
modified = true;
parent.lock();
if (count != null) {
count.incrementAndGet();
}
}
@Override
@ -46,10 +60,14 @@ public class DelegateLock extends ReentrantLock {
public void unlock() {
modified = true;
parent.unlock();
this.notifyAll();
if (count != null) {
if (count.getAndDecrement() <= 0) {
count.incrementAndGet();
}
}
}
public ReentrantLock getParent() {
public Lock getParent() {
return parent;
}
@ -60,27 +78,42 @@ public class DelegateLock extends ReentrantLock {
@Override
public synchronized int getHoldCount() {
return parent.getHoldCount();
throw new UnsupportedOperationException();
}
@Override
public synchronized boolean isHeldByCurrentThread() {
return parent.isHeldByCurrentThread();
throw new UnsupportedOperationException();
}
@Override
public synchronized boolean isLocked() {
return parent.isLocked();
if (parent instanceof ReentrantLock) {
return ((ReentrantLock) parent).isLocked();
}
return count.get() > 0;
}
public void untilFree() {
if (parent instanceof ReentrantLock) {
ReentrantLock rl = (ReentrantLock) parent;
if (rl.isLocked()) {
rl.lock();
rl.unlock();
}
return;
}
while (count.get() > 0);
}
@Override
public synchronized boolean hasWaiters(Condition condition) {
return parent.hasWaiters(condition);
throw new UnsupportedOperationException();
}
@Override
public synchronized int getWaitQueueLength(Condition condition) {
return parent.getWaitQueueLength(condition);
throw new UnsupportedOperationException();
}
@Override