geforkt von Mirrors/FastAsyncWorldEdit
Fix a lot of FAWE-freezing properly
- Add a "loadPrivately" method to be used when GetChunks are called to avoid synchronocity issues with super classes being used on different threads - Synchronise the call method so we're not attempting to call whilst also loading/updating
Dieser Commit ist enthalten in:
Ursprung
e94e3b7b05
Commit
be9866ddb3
@ -376,7 +376,7 @@ public class BukkitGetBlocks_1_15_2 extends CharGetBlocks implements BukkitGetBl
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T extends Future<T>> T call(IChunkSet set, Runnable finalizer) {
|
public synchronized <T extends Future<T>> T call(IChunkSet set, Runnable finalizer) {
|
||||||
forceLoadSections = false;
|
forceLoadSections = false;
|
||||||
copy = createCopy ? new BukkitGetBlocks_1_15_2_Copy(world) : null;
|
copy = createCopy ? new BukkitGetBlocks_1_15_2_Copy(world) : null;
|
||||||
try {
|
try {
|
||||||
@ -424,7 +424,7 @@ public class BukkitGetBlocks_1_15_2 extends CharGetBlocks implements BukkitGetBl
|
|||||||
|
|
||||||
char[] setArr = set.load(layer).clone();
|
char[] setArr = set.load(layer).clone();
|
||||||
if (createCopy) {
|
if (createCopy) {
|
||||||
copy.storeSection(layer, load(layer).clone());
|
copy.storeSection(layer, loadPrivately(layer).clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
ChunkSection newSection;
|
ChunkSection newSection;
|
||||||
@ -458,12 +458,12 @@ public class BukkitGetBlocks_1_15_2 extends CharGetBlocks implements BukkitGetBl
|
|||||||
} else if (existingSection != getSections(false)[layer]) {
|
} else if (existingSection != getSections(false)[layer]) {
|
||||||
this.sections[layer] = existingSection;
|
this.sections[layer] = existingSection;
|
||||||
this.reset();
|
this.reset();
|
||||||
} else if (!Arrays.equals(update(layer, new char[4096]), load(layer))) {
|
} else if (!Arrays.equals(update(layer, new char[4096]), loadPrivately(layer))) {
|
||||||
this.reset(layer);
|
this.reset(layer);
|
||||||
} else if (lock.isModified()) {
|
} else if (lock.isModified()) {
|
||||||
this.reset(layer);
|
this.reset(layer);
|
||||||
}
|
}
|
||||||
newSection = BukkitAdapter_1_15_2.newChunkSection(layer, this::load, setArr, fastmode);
|
newSection = BukkitAdapter_1_15_2.newChunkSection(layer, this::loadPrivately, setArr, fastmode);
|
||||||
if (!BukkitAdapter_1_15_2.setSectionAtomic(sections, existingSection, newSection, layer)) {
|
if (!BukkitAdapter_1_15_2.setSectionAtomic(sections, existingSection, newSection, layer)) {
|
||||||
log.error("Failed to set chunk section:" + chunkX + "," + chunkZ + " layer: " + layer);
|
log.error("Failed to set chunk section:" + chunkX + "," + chunkZ + " layer: " + layer);
|
||||||
} else {
|
} else {
|
||||||
@ -676,6 +676,14 @@ public class BukkitGetBlocks_1_15_2 extends CharGetBlocks implements BukkitGetBl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private char[] loadPrivately(int layer) {
|
||||||
|
if (super.sections[layer].isFull()) {
|
||||||
|
return super.blocks[layer];
|
||||||
|
} else {
|
||||||
|
return BukkitGetBlocks_1_15_2.this.update(layer, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void send(int mask, boolean lighting) {
|
public synchronized void send(int mask, boolean lighting) {
|
||||||
BukkitAdapter_1_15_2.sendChunk(world, chunkX, chunkZ, mask, lighting);
|
BukkitAdapter_1_15_2.sendChunk(world, chunkX, chunkZ, mask, lighting);
|
||||||
|
@ -376,7 +376,7 @@ public class BukkitGetBlocks_1_16_1 extends CharGetBlocks implements BukkitGetBl
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T extends Future<T>> T call(IChunkSet set, Runnable finalizer) {
|
public synchronized <T extends Future<T>> T call(IChunkSet set, Runnable finalizer) {
|
||||||
forceLoadSections = false;
|
forceLoadSections = false;
|
||||||
copy = createCopy ? new BukkitGetBlocks_1_16_1_Copy(world) : null;
|
copy = createCopy ? new BukkitGetBlocks_1_16_1_Copy(world) : null;
|
||||||
try {
|
try {
|
||||||
@ -424,7 +424,7 @@ public class BukkitGetBlocks_1_16_1 extends CharGetBlocks implements BukkitGetBl
|
|||||||
|
|
||||||
char[] setArr = set.load(layer).clone();
|
char[] setArr = set.load(layer).clone();
|
||||||
if (createCopy) {
|
if (createCopy) {
|
||||||
copy.storeSection(layer, load(layer).clone());
|
copy.storeSection(layer, loadPrivately(layer).clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
ChunkSection newSection;
|
ChunkSection newSection;
|
||||||
@ -458,13 +458,13 @@ public class BukkitGetBlocks_1_16_1 extends CharGetBlocks implements BukkitGetBl
|
|||||||
} else if (existingSection != getSections(false)[layer]) {
|
} else if (existingSection != getSections(false)[layer]) {
|
||||||
this.sections[layer] = existingSection;
|
this.sections[layer] = existingSection;
|
||||||
this.reset();
|
this.reset();
|
||||||
} else if (!Arrays.equals(update(layer, new char[4096]), load(layer))) {
|
} else if (!Arrays.equals(update(layer, new char[4096]), loadPrivately(layer))) {
|
||||||
this.reset(layer);
|
this.reset(layer);
|
||||||
} else if (lock.isModified()) {
|
} else if (lock.isModified()) {
|
||||||
this.reset(layer);
|
this.reset(layer);
|
||||||
}
|
}
|
||||||
newSection = BukkitAdapter_1_16_1
|
newSection = BukkitAdapter_1_16_1
|
||||||
.newChunkSection(layer, this::load, setArr, fastmode);
|
.newChunkSection(layer, this::loadPrivately, setArr, fastmode);
|
||||||
if (!BukkitAdapter_1_16_1
|
if (!BukkitAdapter_1_16_1
|
||||||
.setSectionAtomic(sections, existingSection, newSection, layer)) {
|
.setSectionAtomic(sections, existingSection, newSection, layer)) {
|
||||||
log.error("Failed to set chunk section:" + chunkX + "," + chunkZ + " layer: " + layer);
|
log.error("Failed to set chunk section:" + chunkX + "," + chunkZ + " layer: " + layer);
|
||||||
@ -678,6 +678,14 @@ public class BukkitGetBlocks_1_16_1 extends CharGetBlocks implements BukkitGetBl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private char[] loadPrivately(int layer) {
|
||||||
|
if (super.sections[layer].isFull()) {
|
||||||
|
return super.blocks[layer];
|
||||||
|
} else {
|
||||||
|
return BukkitGetBlocks_1_16_1.this.update(layer, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void send(int mask, boolean lighting) {
|
public synchronized void send(int mask, boolean lighting) {
|
||||||
BukkitAdapter_1_16_1.sendChunk(world, chunkX, chunkZ, mask, lighting);
|
BukkitAdapter_1_16_1.sendChunk(world, chunkX, chunkZ, mask, lighting);
|
||||||
|
@ -379,7 +379,7 @@ public class BukkitGetBlocks_1_16_2 extends CharGetBlocks implements BukkitGetBl
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T extends Future<T>> T call(IChunkSet set, Runnable finalizer) {
|
public synchronized <T extends Future<T>> T call(IChunkSet set, Runnable finalizer) {
|
||||||
forceLoadSections = false;
|
forceLoadSections = false;
|
||||||
copy = createCopy ? new BukkitGetBlocks_1_16_2_Copy(world) : null;
|
copy = createCopy ? new BukkitGetBlocks_1_16_2_Copy(world) : null;
|
||||||
try {
|
try {
|
||||||
@ -427,7 +427,7 @@ public class BukkitGetBlocks_1_16_2 extends CharGetBlocks implements BukkitGetBl
|
|||||||
|
|
||||||
char[] setArr = set.load(layer).clone();
|
char[] setArr = set.load(layer).clone();
|
||||||
if (createCopy) {
|
if (createCopy) {
|
||||||
copy.storeSection(layer, load(layer).clone());
|
copy.storeSection(layer, loadPrivately(layer).clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
ChunkSection newSection;
|
ChunkSection newSection;
|
||||||
@ -461,13 +461,13 @@ public class BukkitGetBlocks_1_16_2 extends CharGetBlocks implements BukkitGetBl
|
|||||||
} else if (existingSection != getSections(false)[layer]) {
|
} else if (existingSection != getSections(false)[layer]) {
|
||||||
this.sections[layer] = existingSection;
|
this.sections[layer] = existingSection;
|
||||||
this.reset();
|
this.reset();
|
||||||
} else if (!Arrays.equals(update(layer, new char[4096]), load(layer))) {
|
} else if (!Arrays.equals(update(layer, new char[4096]), loadPrivately(layer))) {
|
||||||
this.reset(layer);
|
this.reset(layer);
|
||||||
} else if (lock.isModified()) {
|
} else if (lock.isModified()) {
|
||||||
this.reset(layer);
|
this.reset(layer);
|
||||||
}
|
}
|
||||||
newSection = BukkitAdapter_1_16_2
|
newSection = BukkitAdapter_1_16_2
|
||||||
.newChunkSection(layer, this::load, setArr, fastmode);
|
.newChunkSection(layer, this::loadPrivately, setArr, fastmode);
|
||||||
if (!BukkitAdapter_1_16_2
|
if (!BukkitAdapter_1_16_2
|
||||||
.setSectionAtomic(sections, existingSection, newSection, layer)) {
|
.setSectionAtomic(sections, existingSection, newSection, layer)) {
|
||||||
log.error("Failed to set chunk section:" + chunkX + "," + chunkZ + " layer: " + layer);
|
log.error("Failed to set chunk section:" + chunkX + "," + chunkZ + " layer: " + layer);
|
||||||
@ -681,6 +681,14 @@ public class BukkitGetBlocks_1_16_2 extends CharGetBlocks implements BukkitGetBl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private char[] loadPrivately(int layer) {
|
||||||
|
if (super.sections[layer].isFull()) {
|
||||||
|
return super.blocks[layer];
|
||||||
|
} else {
|
||||||
|
return BukkitGetBlocks_1_16_2.this.update(layer, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void send(int mask, boolean lighting) {
|
public synchronized void send(int mask, boolean lighting) {
|
||||||
BukkitAdapter_1_16_2.sendChunk(world, chunkX, chunkZ, mask, lighting);
|
BukkitAdapter_1_16_2.sendChunk(world, chunkX, chunkZ, mask, lighting);
|
||||||
|
@ -379,7 +379,7 @@ public class BukkitGetBlocks_1_16_4 extends CharGetBlocks implements BukkitGetBl
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T extends Future<T>> T call(IChunkSet set, Runnable finalizer) {
|
public synchronized <T extends Future<T>> T call(IChunkSet set, Runnable finalizer) {
|
||||||
forceLoadSections = false;
|
forceLoadSections = false;
|
||||||
copy = createCopy ? new BukkitGetBlocks_1_16_4_Copy(world) : null;
|
copy = createCopy ? new BukkitGetBlocks_1_16_4_Copy(world) : null;
|
||||||
try {
|
try {
|
||||||
@ -427,7 +427,7 @@ public class BukkitGetBlocks_1_16_4 extends CharGetBlocks implements BukkitGetBl
|
|||||||
|
|
||||||
char[] setArr = set.load(layer).clone();
|
char[] setArr = set.load(layer).clone();
|
||||||
if (createCopy) {
|
if (createCopy) {
|
||||||
copy.storeSection(layer, load(layer).clone());
|
copy.storeSection(layer, loadPrivately(layer).clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
ChunkSection newSection;
|
ChunkSection newSection;
|
||||||
@ -461,13 +461,13 @@ public class BukkitGetBlocks_1_16_4 extends CharGetBlocks implements BukkitGetBl
|
|||||||
} else if (existingSection != getSections(false)[layer]) {
|
} else if (existingSection != getSections(false)[layer]) {
|
||||||
this.sections[layer] = existingSection;
|
this.sections[layer] = existingSection;
|
||||||
this.reset();
|
this.reset();
|
||||||
} else if (!Arrays.equals(update(layer, new char[4096]), load(layer))) {
|
} else if (!Arrays.equals(update(layer, new char[4096]), loadPrivately(layer))) {
|
||||||
this.reset(layer);
|
this.reset(layer);
|
||||||
} else if (lock.isModified()) {
|
} else if (lock.isModified()) {
|
||||||
this.reset(layer);
|
this.reset(layer);
|
||||||
}
|
}
|
||||||
newSection = BukkitAdapter_1_16_4
|
newSection = BukkitAdapter_1_16_4
|
||||||
.newChunkSection(layer, this::load, setArr, fastmode);
|
.newChunkSection(layer, this::loadPrivately, setArr, fastmode);
|
||||||
if (!BukkitAdapter_1_16_4
|
if (!BukkitAdapter_1_16_4
|
||||||
.setSectionAtomic(sections, existingSection, newSection, layer)) {
|
.setSectionAtomic(sections, existingSection, newSection, layer)) {
|
||||||
log.error("Failed to set chunk section:" + chunkX + "," + chunkZ + " layer: " + layer);
|
log.error("Failed to set chunk section:" + chunkX + "," + chunkZ + " layer: " + layer);
|
||||||
@ -681,6 +681,14 @@ public class BukkitGetBlocks_1_16_4 extends CharGetBlocks implements BukkitGetBl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private char[] loadPrivately(int layer) {
|
||||||
|
if (super.sections[layer].isFull()) {
|
||||||
|
return super.blocks[layer];
|
||||||
|
} else {
|
||||||
|
return BukkitGetBlocks_1_16_4.this.update(layer, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void send(int mask, boolean lighting) {
|
public synchronized void send(int mask, boolean lighting) {
|
||||||
BukkitAdapter_1_16_4.sendChunk(world, chunkX, chunkZ, mask, lighting);
|
BukkitAdapter_1_16_4.sendChunk(world, chunkX, chunkZ, mask, lighting);
|
||||||
|
@ -9,8 +9,6 @@ import org.jetbrains.annotations.Range;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
|
||||||
|
|
||||||
public abstract class CharBlocks implements IBlocks {
|
public abstract class CharBlocks implements IBlocks {
|
||||||
|
|
||||||
public static final Logger logger = LoggerFactory.getLogger(CharBlocks.class);
|
public static final Logger logger = LoggerFactory.getLogger(CharBlocks.class);
|
||||||
|
@ -250,19 +250,8 @@ public class SingleThreadQueueExtent extends ExtentBatchProcessorHolder implemen
|
|||||||
// - memory is low & queue size > num threads + 8
|
// - memory is low & queue size > num threads + 8
|
||||||
// - queue size > target size and primary queue has less than num threads submissions
|
// - queue size > target size and primary queue has less than num threads submissions
|
||||||
if (enabledQueue && ((lowMem && size > Settings.IMP.QUEUE.PARALLEL_THREADS + 8) || (size > Settings.IMP.QUEUE.TARGET_SIZE && Fawe.get().getQueueHandler().isUnderutilized()))) {
|
if (enabledQueue && ((lowMem && size > Settings.IMP.QUEUE.PARALLEL_THREADS + 8) || (size > Settings.IMP.QUEUE.TARGET_SIZE && Fawe.get().getQueueHandler().isUnderutilized()))) {
|
||||||
int i = 0;
|
chunk = chunks.removeFirst();
|
||||||
boolean found = false;
|
final Future future = submitUnchecked(chunk);
|
||||||
while (i < chunks.size() && (chunk = chunks.get(i)) != null) {
|
|
||||||
if (Thread.holdsLock(chunk)) {
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
Future future = null;
|
|
||||||
if (found) {
|
|
||||||
future = submitUnchecked(chunk);
|
|
||||||
}
|
|
||||||
if (future != null && !future.isDone()) {
|
if (future != null && !future.isDone()) {
|
||||||
final int targetSize;
|
final int targetSize;
|
||||||
if (lowMem) {
|
if (lowMem) {
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren