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());
|
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
|
@Override
|
||||||
public T call() {
|
public T call() {
|
||||||
BukkitQueue extent = (BukkitQueue) getExtent();
|
BukkitQueue extent = (BukkitQueue) getExtent();
|
||||||
@ -51,6 +68,7 @@ public class BukkitChunkHolder<T extends Future<T>> extends ChunkHolder {
|
|||||||
if (existingSection == null) {
|
if (existingSection == null) {
|
||||||
newSection = extent.newChunkSection(layer, hasSky, setArr);
|
newSection = extent.newChunkSection(layer, hasSky, setArr);
|
||||||
if (BukkitQueue.setSectionAtomic(sections, null, newSection, layer)) {
|
if (BukkitQueue.setSectionAtomic(sections, null, newSection, layer)) {
|
||||||
|
updateGet(get, nmsChunk, sections, newSection, setArr, layer);
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
existingSection = sections[layer];
|
existingSection = sections[layer];
|
||||||
@ -62,10 +80,7 @@ public class BukkitChunkHolder<T extends Future<T>> extends ChunkHolder {
|
|||||||
}
|
}
|
||||||
DelegateLock lock = BukkitQueue.applyLock(existingSection);
|
DelegateLock lock = BukkitQueue.applyLock(existingSection);
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
if (lock.isLocked()) {
|
lock.untilFree();
|
||||||
lock.lock();
|
|
||||||
lock.unlock();
|
|
||||||
}
|
|
||||||
synchronized (get) {
|
synchronized (get) {
|
||||||
ChunkSection getSection;
|
ChunkSection getSection;
|
||||||
if (get.nmsChunk != nmsChunk) {
|
if (get.nmsChunk != nmsChunk) {
|
||||||
@ -95,6 +110,8 @@ public class BukkitChunkHolder<T extends Future<T>> extends ChunkHolder {
|
|||||||
if (!BukkitQueue.setSectionAtomic(sections, existingSection, newSection, layer)) {
|
if (!BukkitQueue.setSectionAtomic(sections, existingSection, newSection, layer)) {
|
||||||
System.out.println("Failed to set chunk section:" + X + "," + Z + " layer: " + layer);
|
System.out.println("Failed to set chunk section:" + X + "," + Z + " layer: " + layer);
|
||||||
continue;
|
continue;
|
||||||
|
} else {
|
||||||
|
updateGet(get, nmsChunk, sections, newSection, setArr, layer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -64,10 +64,7 @@ public class BukkitGetBlocks extends CharGetBlocks {
|
|||||||
}
|
}
|
||||||
DelegateLock lock = BukkitQueue.applyLock(section);
|
DelegateLock lock = BukkitQueue.applyLock(section);
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
if (lock.isLocked()) {
|
lock.untilFree();
|
||||||
lock.lock();
|
|
||||||
lock.unlock();
|
|
||||||
}
|
|
||||||
lock.setModified(false);
|
lock.setModified(false);
|
||||||
// Efficiently convert ChunkSection to raw data
|
// Efficiently convert ChunkSection to raw data
|
||||||
try {
|
try {
|
||||||
|
@ -39,7 +39,9 @@ import java.lang.reflect.Modifier;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.locks.Lock;
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||||
|
|
||||||
import sun.misc.Unsafe;
|
import sun.misc.Unsafe;
|
||||||
|
|
||||||
@ -135,6 +137,7 @@ public class BukkitQueue extends SimpleCharQueueExtent {
|
|||||||
fieldLock = tmp;
|
fieldLock = tmp;
|
||||||
fieldLock.setAccessible(true);
|
fieldLock.setAccessible(true);
|
||||||
Field modifiersField = Field.class.getDeclaredField("modifiers");
|
Field modifiersField = Field.class.getDeclaredField("modifiers");
|
||||||
|
modifiersField.setAccessible(true);
|
||||||
int modifiers = modifiersField.getInt(fieldLock);
|
int modifiers = modifiersField.getInt(fieldLock);
|
||||||
int newModifiers = modifiers & (~Modifier.FINAL);
|
int newModifiers = modifiers & (~Modifier.FINAL);
|
||||||
if (newModifiers != modifiers) modifiersField.setInt(fieldLock, newModifiers);
|
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;
|
long offset = ((long) layer << CHUNKSECTION_SHIFT) + CHUNKSECTION_BASE;
|
||||||
if (layer >= 0 && layer < sections.length) {
|
if (layer >= 0 && layer < sections.length) {
|
||||||
return UnsafeUtils.getUNSAFE().compareAndSwapObject(sections, offset, expected, value);
|
return UnsafeUtils.getUNSAFE().compareAndSwapObject(sections, offset, expected, value);
|
||||||
@ -162,11 +165,11 @@ public class BukkitQueue extends SimpleCharQueueExtent {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DelegateLock applyLock(ChunkSection section) {
|
protected static DelegateLock applyLock(ChunkSection section) {
|
||||||
try {
|
try {
|
||||||
synchronized (section) {
|
synchronized (section) {
|
||||||
DataPaletteBlock<IBlockData> blocks = section.getBlocks();
|
DataPaletteBlock<IBlockData> blocks = section.getBlocks();
|
||||||
ReentrantLock currentLock = (ReentrantLock) fieldLock.get(blocks);
|
Lock currentLock = (Lock) fieldLock.get(blocks);
|
||||||
if (currentLock instanceof DelegateLock) {
|
if (currentLock instanceof DelegateLock) {
|
||||||
return (DelegateLock) currentLock;
|
return (DelegateLock) currentLock;
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,27 @@
|
|||||||
package com.boydti.fawe.bukkit.beta;
|
package com.boydti.fawe.bukkit.beta;
|
||||||
|
|
||||||
|
import org.apache.commons.lang.mutable.MutableInt;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.concurrent.TimeUnit;
|
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.Condition;
|
||||||
|
import java.util.concurrent.locks.Lock;
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
|
||||||
public class DelegateLock extends ReentrantLock {
|
public class DelegateLock extends ReentrantLock {
|
||||||
private final ReentrantLock parent;
|
private final Lock parent;
|
||||||
private volatile boolean modified;
|
private volatile boolean modified;
|
||||||
|
private final AtomicInteger count;
|
||||||
|
|
||||||
public DelegateLock(ReentrantLock parent) {
|
public DelegateLock(Lock parent) {
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
|
if (!(parent instanceof ReentrantLock)) {
|
||||||
|
count = new AtomicInteger();
|
||||||
|
} else {
|
||||||
|
count = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isModified() {
|
public boolean isModified() {
|
||||||
@ -22,9 +33,12 @@ public class DelegateLock extends ReentrantLock {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void lock() {
|
public synchronized void lock() {
|
||||||
modified = true;
|
modified = true;
|
||||||
parent.lock();
|
parent.lock();
|
||||||
|
if (count != null) {
|
||||||
|
count.incrementAndGet();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -46,10 +60,14 @@ public class DelegateLock extends ReentrantLock {
|
|||||||
public void unlock() {
|
public void unlock() {
|
||||||
modified = true;
|
modified = true;
|
||||||
parent.unlock();
|
parent.unlock();
|
||||||
this.notifyAll();
|
if (count != null) {
|
||||||
|
if (count.getAndDecrement() <= 0) {
|
||||||
|
count.incrementAndGet();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ReentrantLock getParent() {
|
public Lock getParent() {
|
||||||
return parent;
|
return parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,27 +78,42 @@ public class DelegateLock extends ReentrantLock {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized int getHoldCount() {
|
public synchronized int getHoldCount() {
|
||||||
return parent.getHoldCount();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized boolean isHeldByCurrentThread() {
|
public synchronized boolean isHeldByCurrentThread() {
|
||||||
return parent.isHeldByCurrentThread();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized boolean isLocked() {
|
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
|
@Override
|
||||||
public synchronized boolean hasWaiters(Condition condition) {
|
public synchronized boolean hasWaiters(Condition condition) {
|
||||||
return parent.hasWaiters(condition);
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized int getWaitQueueLength(Condition condition) {
|
public synchronized int getWaitQueueLength(Condition condition) {
|
||||||
return parent.getWaitQueueLength(condition);
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren