diff --git a/app/display/representation/src/main/java/org/csstudio/display/builder/representation/RepresentationUpdateThrottle.java b/app/display/representation/src/main/java/org/csstudio/display/builder/representation/RepresentationUpdateThrottle.java index a286a27c3a..e827336126 100644 --- a/app/display/representation/src/main/java/org/csstudio/display/builder/representation/RepresentationUpdateThrottle.java +++ b/app/display/representation/src/main/java/org/csstudio/display/builder/representation/RepresentationUpdateThrottle.java @@ -38,8 +38,8 @@ @SuppressWarnings("nls") public class RepresentationUpdateThrottle { - /** Instance counter to aid in debugging the throttle start/shutdown */ - private static final AtomicInteger instance = new AtomicInteger(); + /** Reference counter to determine when to safely shutdown */ + private static final AtomicInteger reference_count = new AtomicInteger(); /** Period in seconds for logging update performance */ private static final int performance_log_period_secs = Preferences.performance_log_period_secs; @@ -53,6 +53,9 @@ public class RepresentationUpdateThrottle /** Pause between updates to prevent flooding the UI thread */ private static final long update_delay = Preferences.update_delay; + /** Singleton instance of this class */ + private static RepresentationUpdateThrottle instance; + /** Executor for UI thread */ private final Executor gui_executor; @@ -73,10 +76,24 @@ public class RepresentationUpdateThrottle */ private final Set> updateable = new LinkedHashSet<>(); + /** Get instance of this class to perform updates on the UI thread. This class + * is a singleton to ensure that only one thread is scheduling jobs on the UI + * thread. + * + * @param gui_executor Executor for UI thread + */ + public static RepresentationUpdateThrottle getInstance(final Executor gui_executor) { + if(instance == null) { + instance = new RepresentationUpdateThrottle(gui_executor); + } + reference_count.incrementAndGet(); + return instance; + } + /** @param gui_executor Executor for UI thread */ - public RepresentationUpdateThrottle(final Executor gui_executor) + private RepresentationUpdateThrottle(final Executor gui_executor) { - final String name = "RepresentationUpdateThrottle" + instance.incrementAndGet(); + final String name = "RepresentationUpdateThrottle"; logger.log(Level.FINE, "Create " + name); this.gui_executor = gui_executor; throttle_thread = new Thread(this::doRun); @@ -218,7 +235,13 @@ private void updateInUI(final WidgetRepresentation[] representations, /** Shutdown the throttle thread and wait for it to exit */ public void shutdown() { + // Only shutdown if this is the last reference + if (reference_count.decrementAndGet() != 0){ + return; + } + run = false; + instance = null; synchronized (updateable) { updateable.notifyAll(); diff --git a/app/display/representation/src/main/java/org/csstudio/display/builder/representation/ToolkitRepresentation.java b/app/display/representation/src/main/java/org/csstudio/display/builder/representation/ToolkitRepresentation.java index 957fcbd6ee..ee26bc515b 100644 --- a/app/display/representation/src/main/java/org/csstudio/display/builder/representation/ToolkitRepresentation.java +++ b/app/display/representation/src/main/java/org/csstudio/display/builder/representation/ToolkitRepresentation.java @@ -74,7 +74,7 @@ abstract public class ToolkitRepresentation implements E private final boolean edit_mode; - private final RepresentationUpdateThrottle throttle = new RepresentationUpdateThrottle(this); + private final RepresentationUpdateThrottle throttle = RepresentationUpdateThrottle.getInstance(this); /** * Listener list diff --git a/app/display/representation/src/test/java/org/csstudio/display/builder/representation/UpdateThrottleTest.java b/app/display/representation/src/test/java/org/csstudio/display/builder/representation/UpdateThrottleTest.java index d7112f7797..085513d876 100644 --- a/app/display/representation/src/test/java/org/csstudio/display/builder/representation/UpdateThrottleTest.java +++ b/app/display/representation/src/test/java/org/csstudio/display/builder/representation/UpdateThrottleTest.java @@ -28,7 +28,7 @@ @SuppressWarnings("nls") public class UpdateThrottleTest { - private final RepresentationUpdateThrottle throttle = new RepresentationUpdateThrottle(Executors.newSingleThreadExecutor()); + private final RepresentationUpdateThrottle throttle = RepresentationUpdateThrottle.getInstance(Executors.newSingleThreadExecutor()); private class TestWidgetRepresentation extends WidgetRepresentation {