geforkt von Mirrors/FastAsyncWorldEdit
Reuse get array after apply
Dieser Commit ist enthalten in:
Ursprung
18e6c09fdd
Commit
4619fd2b49
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren