1515import java .util .concurrent .atomic .AtomicReference ;
1616import java .util .logging .Level ;
1717
18- import javafx .application .Platform ;
1918import org .csstudio .display .builder .model .DirtyFlag ;
2019import org .csstudio .display .builder .model .DisplayModel ;
2120import org .csstudio .display .builder .model .UntypedWidgetPropertyListener ;
@@ -257,7 +256,7 @@ private void fileChanged(final WidgetProperty<?> property, final Object old_valu
257256
258257 /** Update to the next pending display
259258 *
260- * <p>Executed on the JavaFX Application Thread to serialize the background threads.
259+ * <p>Synchronized to serialize the background threads.
261260 *
262261 * <p>Example: Displays A, B, C are requested in quick succession.
263262 *
@@ -271,56 +270,65 @@ private void fileChanged(final WidgetProperty<?> property, final Object old_valu
271270 * As thread C finally continues, it finds pending_display_and_group empty.
272271 * --> Showing A, then C, skipping B.
273272 */
274- private void updatePendingDisplay (final JobMonitor monitor ) {
275- Platform .runLater (() -> {
276- try {
277- final DisplayAndGroup handle = pending_display_and_group .getAndSet (null );
278- if (handle == null ) {
279- // System.out.println("Nothing to handle");
280- return ;
281- }
282- if (inner == null ) {
283- // System.out.println("Aborted: " + handle);
284- return ;
285- }
273+ private synchronized void updatePendingDisplay (final JobMonitor monitor )
274+ {
275+ try
276+ {
277+ final DisplayAndGroup handle = pending_display_and_group .getAndSet (null );
278+ if (handle == null )
279+ {
280+ // System.out.println("Nothing to handle");
281+ return ;
282+ }
283+ if (inner == null )
284+ {
285+ // System.out.println("Aborted: " + handle);
286+ return ;
287+ }
286288
287- monitor .beginTask ("Load " + handle );
288- try { // Load new model (potentially slow)
289- final DisplayModel new_model = loadDisplayModel (model_widget , handle );
289+ monitor .beginTask ("Load " + handle );
290+ try
291+ { // Load new model (potentially slow)
292+ final DisplayModel new_model = loadDisplayModel (model_widget , handle );
290293
291- // Stop (old) runtime
292- // EmbeddedWidgetRuntime tracks this property to start/stop the embedded model's runtime
293- model_widget .runtimePropEmbeddedModel ().setValue (null );
294+ // Stop (old) runtime
295+ // EmbeddedWidgetRuntime tracks this property to start/stop the embedded model's runtime
296+ model_widget .runtimePropEmbeddedModel ().setValue (null );
294297
295- // Atomically update the 'active' model
296- final DisplayModel old_model = active_content_model .getAndSet (new_model );
297- new_model .propBackgroundColor ().addUntypedPropertyListener (backgroundChangedListener );
298+ // Atomically update the 'active' model
299+ final DisplayModel old_model = active_content_model .getAndSet (new_model );
300+ new_model .propBackgroundColor ().addUntypedPropertyListener (backgroundChangedListener );
298301
299- if (old_model != null ) { // Dispose old model
300- final Future <Object > completion = toolkit .submit (() ->
301- {
302- toolkit .disposeRepresentation (old_model );
303- return null ;
304- });
305- checkCompletion (model_widget , completion , "timeout disposing old representation" );
306- }
307- // Represent new model on UI thread
308- toolkit .onRepresentationStarted ();
302+ if (old_model != null )
303+ { // Dispose old model
309304 final Future <Object > completion = toolkit .submit (() ->
310305 {
311- representContent ( new_model );
306+ toolkit . disposeRepresentation ( old_model );
312307 return null ;
313308 });
314- checkCompletion (model_widget , completion , "timeout representing new content" );
315- // Allow EmbeddedWidgetRuntime to start the new runtime
316- model_widget .runtimePropEmbeddedModel ().setValue (new_model );
317- } catch (Exception ex ) {
318- logger .log (Level .WARNING , "Failed to handle embedded display " + handle , ex );
309+ checkCompletion (model_widget , completion , "timeout disposing old representation" );
319310 }
320- } finally {
321- toolkit .onRepresentationFinished ();
311+ // Represent new model on UI thread
312+ toolkit .onRepresentationStarted ();
313+ final Future <Object > completion = toolkit .submit (() ->
314+ {
315+ representContent (new_model );
316+ return null ;
317+ });
318+ checkCompletion (model_widget , completion , "timeout representing new content" );
319+
320+ // Allow EmbeddedWidgetRuntime to start the new runtime
321+ model_widget .runtimePropEmbeddedModel ().setValue (new_model );
322322 }
323- });
323+ catch (Exception ex )
324+ {
325+ logger .log (Level .WARNING , "Failed to handle embedded display " + handle , ex );
326+ }
327+ }
328+ finally
329+ {
330+ toolkit .onRepresentationFinished ();
331+ }
324332 }
325333
326334 /** @param content_model Model to represent */
@@ -463,28 +471,26 @@ else if (inner.getHeight() != 0.0 && inner.getWidth() != 0.0)
463471 }
464472
465473 @ Override
466- public void dispose () {
467- Platform .runLater (() -> {
468- // When the file name is changed, updatePendingDisplay()
469- // will atomically update the active_content_model,
470- // represent the new model, and then set runtimePropEmbeddedModel.
471- //
472- // Fetching the embedded model from active_content_model
473- // could dispose a representation that hasn't been represented, yet.
474- // Fetching the embedded model from runtimePropEmbeddedModel
475- // could fail to dispose what's just now being represented.
476- //
477- // --> Very unlikely to happen because runtime has been stopped,
478- // so nothing is changing the file name right now.
479-
480- final DisplayModel em = active_content_model .getAndSet (null );
481- model_widget .runtimePropEmbeddedModel ().setValue (null );
482-
483- if (inner != null && em != null )
484- toolkit .disposeRepresentation (em );
485- inner = null ;
486-
487- super .dispose ();
488- });
474+ public void dispose ()
475+ {
476+ // When the file name is changed, updatePendingDisplay()
477+ // will atomically update the active_content_model,
478+ // represent the new model, and then set runtimePropEmbeddedModel.
479+ //
480+ // Fetching the embedded model from active_content_model
481+ // could dispose a representation that hasn't been represented, yet.
482+ // Fetching the embedded model from runtimePropEmbeddedModel
483+ // could fail to dispose what's just now being represented.
484+ //
485+ // --> Very unlikely to happen because runtime has been stopped,
486+ // so nothing is changing the file name right now.
487+ final DisplayModel em = active_content_model .getAndSet (null );
488+ model_widget .runtimePropEmbeddedModel ().setValue (null );
489+
490+ if (inner != null && em != null )
491+ toolkit .disposeRepresentation (em );
492+ inner = null ;
493+
494+ super .dispose ();
489495 }
490496}
0 commit comments