Remove unnecessary synchronization in ChunkSet

This commit is contained in:
themode 2022-02-14 07:46:19 +01:00
parent 01e5be9454
commit 028b187eda

View File

@ -29,9 +29,6 @@ public final class ViewEngine {
private final int range; private final int range;
private final Set<Player> manualViewers = new HashSet<>(); private final Set<Player> manualViewers = new HashSet<>();
private Instance instance;
private Point lastPoint;
// Decide if this entity should be viewable to X players // Decide if this entity should be viewable to X players
public final Option<Player> viewableOption; public final Option<Player> viewableOption;
// Decide if this entity should view X entities // Decide if this entity should view X entities
@ -40,6 +37,8 @@ public final class ViewEngine {
private final Set<Player> set; private final Set<Player> set;
private final Object mutex = this; private final Object mutex = this;
private volatile TrackedLocation trackedLocation;
public ViewEngine(@Nullable Entity entity, public ViewEngine(@Nullable Entity entity,
Consumer<Player> autoViewableAddition, Consumer<Player> autoViewableRemoval, Consumer<Player> autoViewableAddition, Consumer<Player> autoViewableRemoval,
Consumer<Entity> autoViewerAddition, Consumer<Entity> autoViewerRemoval) { Consumer<Entity> autoViewerAddition, Consumer<Entity> autoViewerRemoval) {
@ -64,10 +63,10 @@ public final class ViewEngine {
} }
public void updateTracker(@Nullable Instance instance, @NotNull Point point) { public void updateTracker(@Nullable Instance instance, @NotNull Point point) {
synchronized (mutex) { this.trackedLocation = instance != null ? new TrackedLocation(instance, point) : null;
this.instance = instance; }
this.lastPoint = point;
} record TrackedLocation(Instance instance, Point point) {
} }
public boolean manualAdd(@NotNull Player player) { public boolean manualAdd(@NotNull Player player) {
@ -189,22 +188,26 @@ public final class ViewEngine {
public void updateRule(Predicate<T> predicate) { public void updateRule(Predicate<T> predicate) {
synchronized (mutex) { synchronized (mutex) {
this.predicate = predicate; this.predicate = predicate;
updateRule(); updateRule0(predicate);
} }
} }
public void updateRule() { public void updateRule() {
synchronized (mutex) { synchronized (mutex) {
update(loopPredicate, entity -> { updateRule0(predicate);
final boolean result = predicate.test(entity);
if (result != isRegistered(entity)) {
if (result) addition.accept(entity);
else removal.accept(entity);
}
});
} }
} }
void updateRule0(Predicate<T> predicate) {
update(loopPredicate, entity -> {
final boolean result = predicate.test(entity);
if (result != isRegistered(entity)) {
if (result) addition.accept(entity);
else removal.accept(entity);
}
});
}
private void update(Predicate<T> visibilityPredicate, private void update(Predicate<T> visibilityPredicate,
Consumer<T> action) { Consumer<T> action) {
references().forEach(entity -> { references().forEach(entity -> {
@ -216,16 +219,18 @@ public final class ViewEngine {
} }
private Stream<T> references() { private Stream<T> references() {
final Instance instance = ViewEngine.this.instance; final TrackedLocation trackedLocation = ViewEngine.this.trackedLocation;
if (instance == null) return Stream.empty(); if (trackedLocation == null) return Stream.empty();
var references = instance.getEntityTracker().references(lastPoint, range, target); final Instance instance = trackedLocation.instance();
final Point point = trackedLocation.point();
var references = instance.getEntityTracker().references(point, range, target);
Stream<T> result = references.stream().flatMap(Collection::stream); Stream<T> result = references.stream().flatMap(Collection::stream);
if (instance instanceof InstanceContainer container) { if (instance instanceof InstanceContainer container) {
// References from shared instances must be added to the result. // References from shared instances must be added to the result.
final List<SharedInstance> shared = container.getSharedInstances(); final List<SharedInstance> shared = container.getSharedInstances();
if (!shared.isEmpty()) { if (!shared.isEmpty()) {
Stream<T> sharedInstanceStream = shared.stream().<List<T>>mapMulti((inst, consumer) -> { Stream<T> sharedInstanceStream = shared.stream().<List<T>>mapMulti((inst, consumer) -> {
var ref = inst.getEntityTracker().references(lastPoint, range, target); var ref = inst.getEntityTracker().references(point, range, target);
ref.forEach(consumer); ref.forEach(consumer);
}).flatMap(Collection::stream); }).flatMap(Collection::stream);
result = Stream.concat(result, sharedInstanceStream); result = Stream.concat(result, sharedInstanceStream);
@ -238,23 +243,17 @@ public final class ViewEngine {
final class ChunkSet extends AbstractSet<Player> { final class ChunkSet extends AbstractSet<Player> {
@Override @Override
public @NotNull Iterator<Player> iterator() { public @NotNull Iterator<Player> iterator() {
synchronized (mutex) { return viewableOption.references().toList().iterator();
return viewableOption.references().toList().iterator();
}
} }
@Override @Override
public int size() { public int size() {
synchronized (mutex) { return (int) viewableOption.references().count();
return (int) viewableOption.references().count();
}
} }
@Override @Override
public void forEach(Consumer<? super Player> action) { public void forEach(Consumer<? super Player> action) {
synchronized (mutex) { viewableOption.references().forEach(action);
viewableOption.references().forEach(action);
}
} }
} }