diff --git a/projects/common/src/main/java/dan200/computercraft/shared/computer/metrics/GlobalMetrics.java b/projects/common/src/main/java/dan200/computercraft/shared/computer/metrics/GlobalMetrics.java index b7fb19b62b..2e3b4e4130 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/computer/metrics/GlobalMetrics.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/computer/metrics/GlobalMetrics.java @@ -46,12 +46,14 @@ public BasicComputerMetricsObserver getMetricsInstance(UUID uuid) { * Add a new global metrics observer. This will receive metrics data for all computers. * * @param tracker The observer to add. + * @return Whether the observer was added. {@code false} if the observer was already registered. */ - public void addObserver(ComputerMetricsObserver tracker) { + public boolean addObserver(ComputerMetricsObserver tracker) { synchronized (lock) { - if (trackers.contains(tracker)) return; + if (trackers.contains(tracker)) return false; trackers.add(tracker); enabled = true; + return true; } } @@ -59,11 +61,13 @@ public void addObserver(ComputerMetricsObserver tracker) { * Remove a previously-registered global metrics observer. * * @param tracker The observer to add. + * @return Whether the observer was removed. {@code false} if the observer was not registered. */ - public void removeObserver(ComputerMetricsObserver tracker) { + public boolean removeObserver(ComputerMetricsObserver tracker) { synchronized (lock) { - trackers.remove(tracker); + var changed = trackers.remove(tracker); enabled = !trackers.isEmpty(); + return changed; } } diff --git a/projects/common/src/main/java/dan200/computercraft/shared/computer/metrics/basic/BasicComputerMetricsObserver.java b/projects/common/src/main/java/dan200/computercraft/shared/computer/metrics/basic/BasicComputerMetricsObserver.java index 2738cb63b5..90eefbb64a 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/computer/metrics/basic/BasicComputerMetricsObserver.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/computer/metrics/basic/BasicComputerMetricsObserver.java @@ -10,6 +10,7 @@ import dan200.computercraft.shared.computer.metrics.ComputerMetricsObserver; import dan200.computercraft.shared.computer.metrics.GlobalMetrics; +import javax.annotation.concurrent.GuardedBy; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -21,29 +22,31 @@ */ public class BasicComputerMetricsObserver implements ComputerMetricsObserver { private final GlobalMetrics owner; - private boolean tracking = false; + @GuardedBy("this") private final List timings = new ArrayList<>(); + + @GuardedBy("this") private final Map timingLookup = new MapMaker().weakKeys().makeMap(); public BasicComputerMetricsObserver(GlobalMetrics owner) { this.owner = owner; } - public synchronized void start() { - if (!tracking) owner.addObserver(this); - tracking = true; + public void start() { + if (!owner.addObserver(this)) return; - timings.clear(); - timingLookup.clear(); + synchronized (this) { + timings.clear(); + timingLookup.clear(); + } } - public synchronized boolean stop() { - if (!tracking) return false; - - owner.removeObserver(this); - tracking = false; - timingLookup.clear(); + public boolean stop() { + if (!owner.removeObserver(this)) return false; + synchronized (this) { + timingLookup.clear(); + } return true; } @@ -57,6 +60,7 @@ public synchronized List getTimings() { return new ArrayList<>(timings); } + @GuardedBy("this") private ComputerMetrics getMetrics(ServerComputer computer) { var existing = timingLookup.get(computer); if (existing != null) return existing;