net.minestom.server.snapshot.SnapshotUpdaterImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of minestom-snapshots Show documentation
Show all versions of minestom-snapshots Show documentation
1.20.4 Lightweight Minecraft server
package net.minestom.server.snapshot;
import org.jetbrains.annotations.NotNull;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
final class SnapshotUpdaterImpl implements SnapshotUpdater {
private final IdentityHashMap> referenceMap = new IdentityHashMap<>();
private IdentityHashMap> readOnlyReferenceMap;
private List queue = new ArrayList<>();
static @NotNull T update(@NotNull Snapshotable snapshotable) {
var updater = new SnapshotUpdaterImpl();
var ref = updater.reference(snapshotable);
updater.update();
return (T) ref.get();
}
@Override
public @NotNull AtomicReference reference(@NotNull Snapshotable snapshotable) {
AtomicReference ref;
// Very often the same snapshotable is referenced multiple times.
var readOnly = this.readOnlyReferenceMap;
if (readOnly != null && (ref = readOnly.get(snapshotable)) != null) {
return (AtomicReference) ref;
}
// If this is a new snapshotable, we need to create a new reference.
synchronized (this) {
ref = new AtomicReference<>();
var prev = referenceMap.putIfAbsent(snapshotable, ref);
if (prev != null) return (AtomicReference) prev;
this.queue.add(new Entry(snapshotable, ref));
return (AtomicReference) ref;
}
}
record Entry(Snapshotable snapshotable, AtomicReference ref) {
}
void update() {
List temp;
while (!(temp = new ArrayList<>(queue)).isEmpty()) {
queue = new ArrayList<>();
readOnlyReferenceMap = (IdentityHashMap>) referenceMap.clone();
temp.parallelStream().forEach(entry -> {
Snapshotable snap = entry.snapshotable;
entry.ref.set(Objects.requireNonNull(snap.updateSnapshot(this), "Snapshot must not be null after an update!"));
});
}
}
}