mirror of
https://github.com/BX-Team/DivineMC.git
synced 2025-12-19 14:59:25 +00:00
fix ReferenceList crash and concurrency
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
--- a/src/main/java/ca/spottedleaf/moonrise/common/list/EntityList.java
|
||||
+++ b/src/main/java/ca/spottedleaf/moonrise/common/list/EntityList.java
|
||||
@@ -1,5 +_,7 @@
|
||||
package ca.spottedleaf.moonrise.common.list;
|
||||
|
||||
+import it.unimi.dsi.fastutil.ints.Int2IntMap;
|
||||
+import it.unimi.dsi.fastutil.ints.Int2IntMaps;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import java.util.Arrays;
|
||||
@@ -13,7 +_,7 @@
|
||||
*/
|
||||
public final class EntityList implements Iterable<Entity> {
|
||||
|
||||
- private final Int2IntOpenHashMap entityToIndex = new Int2IntOpenHashMap(2, 0.8f);
|
||||
+ private final Int2IntMap entityToIndex = Int2IntMaps.synchronize(new Int2IntOpenHashMap(2, 0.8f));
|
||||
{
|
||||
this.entityToIndex.defaultReturnValue(Integer.MIN_VALUE);
|
||||
}
|
||||
@@ -27,11 +_,11 @@
|
||||
return this.count;
|
||||
}
|
||||
|
||||
- public boolean contains(final Entity entity) {
|
||||
+ public synchronized boolean contains(final Entity entity) {
|
||||
return this.entityToIndex.containsKey(entity.getId());
|
||||
}
|
||||
|
||||
- public boolean remove(final Entity entity) {
|
||||
+ public synchronized boolean remove(final Entity entity) {
|
||||
final int index = this.entityToIndex.remove(entity.getId());
|
||||
if (index == Integer.MIN_VALUE) {
|
||||
return false;
|
||||
@@ -50,7 +_,7 @@
|
||||
return true;
|
||||
}
|
||||
|
||||
- public boolean add(final Entity entity) {
|
||||
+ public synchronized boolean add(final Entity entity) {
|
||||
final int count = this.count;
|
||||
final int currIndex = this.entityToIndex.putIfAbsent(entity.getId(), count);
|
||||
|
||||
@@ -82,18 +_,18 @@
|
||||
return this.entities[index];
|
||||
}
|
||||
|
||||
- public Entity[] getRawData() {
|
||||
+ public synchronized Entity[] getRawData() {
|
||||
return this.entities;
|
||||
}
|
||||
|
||||
- public void clear() {
|
||||
+ public synchronized void clear() {
|
||||
this.entityToIndex.clear();
|
||||
Arrays.fill(this.entities, 0, this.count, null);
|
||||
this.count = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
- public Iterator<Entity> iterator() {
|
||||
+ public synchronized Iterator<Entity> iterator() {
|
||||
return new Iterator<>() {
|
||||
private Entity lastRet;
|
||||
private int current;
|
||||
@@ -0,0 +1,165 @@
|
||||
--- a/src/main/java/ca/spottedleaf/moonrise/common/list/ReferenceList.java
|
||||
+++ b/src/main/java/ca/spottedleaf/moonrise/common/list/ReferenceList.java
|
||||
@@ -1,142 +_,24 @@
|
||||
package ca.spottedleaf.moonrise.common.list;
|
||||
|
||||
-import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap;
|
||||
-import java.util.Arrays;
|
||||
-import java.util.Iterator;
|
||||
-import java.util.NoSuchElementException;
|
||||
-
|
||||
-public final class ReferenceList<E> implements Iterable<E> {
|
||||
-
|
||||
- private static final Object[] EMPTY_LIST = new Object[0];
|
||||
-
|
||||
- private final Reference2IntOpenHashMap<E> referenceToIndex;
|
||||
- private E[] references;
|
||||
- private int count;
|
||||
-
|
||||
- public ReferenceList() {
|
||||
- this((E[])EMPTY_LIST);
|
||||
- }
|
||||
-
|
||||
- public ReferenceList(final E[] referenceArray) {
|
||||
- this.references = referenceArray;
|
||||
- this.referenceToIndex = new Reference2IntOpenHashMap<>(2, 0.8f);
|
||||
- this.referenceToIndex.defaultReturnValue(Integer.MIN_VALUE);
|
||||
- }
|
||||
-
|
||||
- private ReferenceList(final E[] references, final int count, final Reference2IntOpenHashMap<E> referenceToIndex) {
|
||||
- this.references = references;
|
||||
- this.count = count;
|
||||
- this.referenceToIndex = referenceToIndex;
|
||||
- }
|
||||
-
|
||||
- public ReferenceList<E> copy() {
|
||||
- return new ReferenceList<>(this.references.clone(), this.count, this.referenceToIndex.clone());
|
||||
- }
|
||||
-
|
||||
- public int size() {
|
||||
- return this.count;
|
||||
- }
|
||||
-
|
||||
- public boolean contains(final E obj) {
|
||||
- return this.referenceToIndex.containsKey(obj);
|
||||
- }
|
||||
-
|
||||
- public boolean remove(final E obj) {
|
||||
- final int index = this.referenceToIndex.removeInt(obj);
|
||||
- if (index == Integer.MIN_VALUE) {
|
||||
- return false;
|
||||
- }
|
||||
-
|
||||
- // move the object at the end to this index
|
||||
- final int endIndex = --this.count;
|
||||
- final E end = (E)this.references[endIndex];
|
||||
- if (index != endIndex) {
|
||||
- // not empty after this call
|
||||
- this.referenceToIndex.put(end, index); // update index
|
||||
- }
|
||||
- this.references[index] = end;
|
||||
- this.references[endIndex] = null;
|
||||
-
|
||||
- return true;
|
||||
- }
|
||||
-
|
||||
- public boolean add(final E obj) {
|
||||
- final int count = this.count;
|
||||
- final int currIndex = this.referenceToIndex.putIfAbsent(obj, count);
|
||||
-
|
||||
- if (currIndex != Integer.MIN_VALUE) {
|
||||
- return false; // already in this list
|
||||
- }
|
||||
-
|
||||
- E[] list = this.references;
|
||||
-
|
||||
- if (list.length == count) {
|
||||
- // resize required
|
||||
- list = this.references = Arrays.copyOf(list, (int)Math.max(4L, count * 2L)); // overflow results in negative
|
||||
- }
|
||||
-
|
||||
- list[count] = obj;
|
||||
- this.count = count + 1;
|
||||
-
|
||||
- return true;
|
||||
- }
|
||||
-
|
||||
- public E getChecked(final int index) {
|
||||
- if (index < 0 || index >= this.count) {
|
||||
- throw new IndexOutOfBoundsException("Index: " + index + " is out of bounds, size: " + this.count);
|
||||
- }
|
||||
- return this.references[index];
|
||||
- }
|
||||
-
|
||||
- public E getUnchecked(final int index) {
|
||||
- return this.references[index];
|
||||
- }
|
||||
-
|
||||
- public Object[] getRawData() {
|
||||
- return this.references;
|
||||
- }
|
||||
-
|
||||
- public E[] getRawDataUnchecked() {
|
||||
- return this.references;
|
||||
- }
|
||||
-
|
||||
- public void clear() {
|
||||
- this.referenceToIndex.clear();
|
||||
- Arrays.fill(this.references, 0, this.count, null);
|
||||
- this.count = 0;
|
||||
- }
|
||||
-
|
||||
- @Override
|
||||
- public Iterator<E> iterator() {
|
||||
- return new Iterator<>() {
|
||||
- private E lastRet;
|
||||
- private int current;
|
||||
-
|
||||
- @Override
|
||||
- public boolean hasNext() {
|
||||
- return this.current < ReferenceList.this.count;
|
||||
- }
|
||||
-
|
||||
- @Override
|
||||
- public E next() {
|
||||
- if (this.current >= ReferenceList.this.count) {
|
||||
- throw new NoSuchElementException();
|
||||
- }
|
||||
- return this.lastRet = ReferenceList.this.references[this.current++];
|
||||
- }
|
||||
-
|
||||
- @Override
|
||||
- public void remove() {
|
||||
- final E lastRet = this.lastRet;
|
||||
-
|
||||
- if (lastRet == null) {
|
||||
- throw new IllegalStateException();
|
||||
- }
|
||||
- this.lastRet = null;
|
||||
-
|
||||
- ReferenceList.this.remove(lastRet);
|
||||
- --this.current;
|
||||
- }
|
||||
- };
|
||||
+import it.unimi.dsi.fastutil.objects.ReferenceArrayList;
|
||||
+import it.unimi.dsi.fastutil.objects.ReferenceLists;
|
||||
+
|
||||
+public class ReferenceList<E> extends ReferenceLists.SynchronizedList<E> {
|
||||
+ public ReferenceList(E[] elements) {
|
||||
+ super(new RefListInner<>(elements));
|
||||
+ }
|
||||
+
|
||||
+ public synchronized E[] getRawDataUnchecked() {
|
||||
+ return ((RefListInner<E>) this.list).getRawDataUnchecked();
|
||||
+ }
|
||||
+
|
||||
+ public static class RefListInner<A> extends ReferenceArrayList<A> {
|
||||
+ public RefListInner(A[] elements) {
|
||||
+ super(elements, true);
|
||||
+ }
|
||||
+
|
||||
+ public A[] getRawDataUnchecked() {
|
||||
+ return this.a;
|
||||
+ }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
--- a/src/main/java/ca/spottedleaf/moonrise/common/list/ShortList.java
|
||||
+++ b/src/main/java/ca/spottedleaf/moonrise/common/list/ShortList.java
|
||||
@@ -1,11 +_,13 @@
|
||||
package ca.spottedleaf.moonrise.common.list;
|
||||
|
||||
+import it.unimi.dsi.fastutil.shorts.Short2ShortMap;
|
||||
+import it.unimi.dsi.fastutil.shorts.Short2ShortMaps;
|
||||
import it.unimi.dsi.fastutil.shorts.Short2ShortOpenHashMap;
|
||||
import java.util.Arrays;
|
||||
|
||||
public final class ShortList {
|
||||
|
||||
- private final Short2ShortOpenHashMap map = new Short2ShortOpenHashMap();
|
||||
+ private final Short2ShortMap map = Short2ShortMaps.synchronize(new Short2ShortOpenHashMap());
|
||||
{
|
||||
this.map.defaultReturnValue(Short.MIN_VALUE);
|
||||
}
|
||||
@@ -13,13 +_,13 @@
|
||||
private static final short[] EMPTY_LIST = new short[0];
|
||||
|
||||
private short[] byIndex = EMPTY_LIST;
|
||||
- private short count;
|
||||
+ private volatile short count;
|
||||
|
||||
public int size() {
|
||||
- return (int)this.count;
|
||||
+ return this.count;
|
||||
}
|
||||
|
||||
- public short getRaw(final int index) {
|
||||
+ public synchronized short getRaw(final int index) {
|
||||
return this.byIndex[index];
|
||||
}
|
||||
|
||||
@@ -30,8 +_,8 @@
|
||||
}
|
||||
}
|
||||
|
||||
- public boolean add(final short value) {
|
||||
- final int count = (int)this.count;
|
||||
+ public synchronized boolean add(final short value) {
|
||||
+ final int count = this.count;
|
||||
final short currIndex = this.map.putIfAbsent(value, (short)count);
|
||||
|
||||
if (currIndex != Short.MIN_VALUE) {
|
||||
@@ -51,7 +_,7 @@
|
||||
return true;
|
||||
}
|
||||
|
||||
- public boolean remove(final short value) {
|
||||
+ public synchronized boolean remove(final short value) {
|
||||
final short index = this.map.remove(value);
|
||||
if (index == Short.MIN_VALUE) {
|
||||
return false;
|
||||
@@ -70,7 +_,7 @@
|
||||
return true;
|
||||
}
|
||||
|
||||
- public void clear() {
|
||||
+ public synchronized void clear() {
|
||||
this.count = (short)0;
|
||||
this.map.clear();
|
||||
}
|
||||
Reference in New Issue
Block a user