Use an object array for synchronising on internal chunk sections rather than the sections array itself.

- Synchronising on full sections synchronises on the global FULL instance (bad)
- Synchronising on empty sections synchronises on the local empty instance (bad)
- Leads to needless thread locking, and raises the possibility of cyclic locks considerably
This commit is contained in:
dordsor21 2021-09-15 01:20:04 +01:00 committed by GitHub
parent e989a4ebb0
commit f10dbe7387
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 27 additions and 12 deletions

View File

@ -40,7 +40,7 @@ public abstract class CharBlocks implements IBlocks {
@Override
public char[] get(CharBlocks blocks, int layer, boolean aggressive) {
synchronized (this) {
synchronized (blocks.sectionLocks[layer]) {
char[] arr = blocks.blocks[layer];
if (arr == null) {
arr = blocks.blocks[layer] = blocks.update(layer, null, aggressive);
@ -67,6 +67,7 @@ public abstract class CharBlocks implements IBlocks {
};
public char[][] blocks;
public Section[] sections;
public Object[] sectionLocks;
protected int minSectionPosition;
protected int maxSectionPosition;
protected int sectionCount;
@ -80,8 +81,10 @@ public abstract class CharBlocks implements IBlocks {
this.sectionCount = maxSectionPosition - minSectionPosition + 1;
blocks = new char[sectionCount][];
sections = new Section[sectionCount];
sectionLocks = new Object[sectionCount];
for (int i = 0; i < sectionCount; i++) {
sections[i] = empty;
sectionLocks[i] = new Object();
}
}
@ -99,12 +102,14 @@ public abstract class CharBlocks implements IBlocks {
}
@Override
public synchronized boolean trim(boolean aggressive, int layer) {
public boolean trim(boolean aggressive, int layer) {
boolean result = true;
if (!sections[layer].isFull() && blocks[layer] != null) {
blocks[layer] = null;
} else {
result = false;
synchronized (sectionLocks[layer]) {
if (!sections[layer].isFull() && blocks[layer] != null) {
blocks[layer] = null;
} else {
result = false;
}
}
return result;
}
@ -117,12 +122,14 @@ public abstract class CharBlocks implements IBlocks {
return null;
}
public synchronized void reset(int layer) {
public void reset(int layer) {
layer -= minSectionPosition;
sections[layer] = empty;
synchronized (sectionLocks[layer]) {
sections[layer] = empty;
}
}
public synchronized char[] update(int layer, char[] data, boolean aggressive) {
public char[] update(int layer, char[] data, boolean aggressive) {
if (data == null) {
return new char[4096];
}
@ -142,7 +149,7 @@ public abstract class CharBlocks implements IBlocks {
@Override
public char[] load(int layer) {
layer -= minSectionPosition;
synchronized (sections[layer]) {
synchronized (sectionLocks[layer]) {
return sections[layer].get(this, layer);
}
}
@ -208,7 +215,7 @@ public abstract class CharBlocks implements IBlocks {
return sections[layer].get(this, layer, index);
}
public synchronized final void set(int layer, int index, char value) throws
public final void set(int layer, int index, char value) throws
ArrayIndexOutOfBoundsException {
layer -= minSectionPosition;
sections[layer].set(this, layer, index, value);
@ -231,7 +238,7 @@ public abstract class CharBlocks implements IBlocks {
return section[index];
}
public final void set(CharBlocks blocks, int layer, int index, char value) {
public final synchronized void set(CharBlocks blocks, int layer, int index, char value) {
get(blocks, layer)[index] = value;
}

View File

@ -331,13 +331,17 @@ public class CharSetBlocks extends CharBlocks implements IChunkSet {
sectionCount += diff;
char[][] tmpBlocks = new char[sectionCount][];
Section[] tmpSections = new Section[sectionCount];
Object[] tmpSectionLocks = new Object[sectionCount];
System.arraycopy(blocks, 0, tmpBlocks, diff, blocks.length);
System.arraycopy(sections, 0, tmpSections, diff, sections.length);
System.arraycopy(sectionLocks, 0, tmpSectionLocks, diff, sections.length);
for (int i = 0; i < diff; i++) {
tmpSections[i] = empty;
tmpSectionLocks[i] = new Object();
}
blocks = tmpBlocks;
sections = tmpSections;
sectionLocks = tmpSectionLocks;
minSectionPosition = layer;
if (biomes != null) {
BiomeType[] tmpBiomes = new BiomeType[sectionCount * 64];
@ -359,13 +363,17 @@ public class CharSetBlocks extends CharBlocks implements IChunkSet {
sectionCount += diff;
char[][] tmpBlocks = new char[sectionCount][];
Section[] tmpSections = new Section[sectionCount];
Object[] tmpSectionLocks = new Object[sectionCount];
System.arraycopy(blocks, 0, tmpBlocks, 0, blocks.length);
System.arraycopy(sections, 0, tmpSections, 0, sections.length);
System.arraycopy(sectionLocks, 0, tmpSectionLocks, 0, sections.length);
for (int i = sectionCount - diff; i < sectionCount; i++) {
tmpSections[i] = empty;
tmpSectionLocks[i] = new Object();
}
blocks = tmpBlocks;
sections = tmpSections;
sectionLocks = tmpSectionLocks;
maxSectionPosition = layer;
if (biomes != null) {
BiomeType[] tmpBiomes = new BiomeType[sectionCount * 64];