123 lines
3.6 KiB
Java
123 lines
3.6 KiB
Java
package com.hypixel.hytale.assetstore.map;
|
|
|
|
import com.hypixel.hytale.assetstore.codec.AssetCodec;
|
|
import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
|
import it.unimi.dsi.fastutil.objects.Object2IntOpenCustomHashMap;
|
|
import java.nio.file.Path;
|
|
import java.util.Map;
|
|
import java.util.Set;
|
|
import java.util.Map.Entry;
|
|
import java.util.concurrent.locks.StampedLock;
|
|
import java.util.function.ToIntBiFunction;
|
|
import javax.annotation.Nonnull;
|
|
|
|
public class ProvidedIndexAssetMap<K, T extends JsonAssetWithMap<K, ProvidedIndexAssetMap<K, T>>> extends AssetMapWithIndexes<K, T> {
|
|
private final StampedLock keyToIndexLock = new StampedLock();
|
|
private final Object2IntMap<K> keyToIndex = new Object2IntOpenCustomHashMap(CaseInsensitiveHashStrategy.getInstance());
|
|
private final ToIntBiFunction<K, T> indexGetter;
|
|
|
|
public ProvidedIndexAssetMap(ToIntBiFunction<K, T> indexGetter) {
|
|
this.indexGetter = indexGetter;
|
|
this.keyToIndex.defaultReturnValue(Integer.MIN_VALUE);
|
|
}
|
|
|
|
public int getIndex(K key) {
|
|
long stamp = this.keyToIndexLock.tryOptimisticRead();
|
|
int value = this.keyToIndex.getInt(key);
|
|
if (this.keyToIndexLock.validate(stamp)) {
|
|
return value;
|
|
} else {
|
|
stamp = this.keyToIndexLock.readLock();
|
|
|
|
int var5;
|
|
try {
|
|
var5 = this.keyToIndex.getInt(key);
|
|
} finally {
|
|
this.keyToIndexLock.unlockRead(stamp);
|
|
}
|
|
|
|
return var5;
|
|
}
|
|
}
|
|
|
|
public int getIndexOrDefault(K key, int def) {
|
|
long stamp = this.keyToIndexLock.tryOptimisticRead();
|
|
int value = this.keyToIndex.getOrDefault(key, def);
|
|
if (this.keyToIndexLock.validate(stamp)) {
|
|
return value;
|
|
} else {
|
|
stamp = this.keyToIndexLock.readLock();
|
|
|
|
int var6;
|
|
try {
|
|
var6 = this.keyToIndex.getOrDefault(key, def);
|
|
} finally {
|
|
this.keyToIndexLock.unlockRead(stamp);
|
|
}
|
|
|
|
return var6;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected void clear() {
|
|
super.clear();
|
|
long stamp = this.keyToIndexLock.writeLock();
|
|
|
|
try {
|
|
this.keyToIndex.clear();
|
|
} finally {
|
|
this.keyToIndexLock.unlockWrite(stamp);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected void putAll(
|
|
@Nonnull String packKey,
|
|
@Nonnull AssetCodec<K, T> codec,
|
|
@Nonnull Map<K, T> loadedAssets,
|
|
@Nonnull Map<K, Path> loadedKeyToPathMap,
|
|
@Nonnull Map<K, Set<K>> loadedAssetChildren
|
|
) {
|
|
super.putAll(packKey, codec, loadedAssets, loadedKeyToPathMap, loadedAssetChildren);
|
|
long stamp = this.keyToIndexLock.writeLock();
|
|
|
|
try {
|
|
for (Entry<K, T> entry : loadedAssets.entrySet()) {
|
|
K key = entry.getKey();
|
|
T value = entry.getValue();
|
|
int index;
|
|
if ((index = this.keyToIndex.getInt(key)) == Integer.MIN_VALUE) {
|
|
this.keyToIndex.put(key, index = this.indexGetter.applyAsInt(key, value));
|
|
}
|
|
|
|
this.putAssetTag(codec, key, index, value);
|
|
}
|
|
} finally {
|
|
this.keyToIndexLock.unlockWrite(stamp);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected Set<K> remove(@Nonnull Set<K> keys) {
|
|
Set<K> remove = super.remove(keys);
|
|
long stamp = this.keyToIndexLock.writeLock();
|
|
|
|
try {
|
|
for (K key : keys) {
|
|
int index = this.keyToIndex.removeInt(key);
|
|
this.indexedTagStorage.forEachWithInt((_k, value, idx) -> value.remove(idx), index);
|
|
}
|
|
} finally {
|
|
this.keyToIndexLock.unlockWrite(stamp);
|
|
}
|
|
|
|
return remove;
|
|
}
|
|
|
|
@Override
|
|
public boolean requireReplaceOnRemove() {
|
|
return false;
|
|
}
|
|
}
|