Skip to content

Commit

Permalink
Fixes #3261.
Browse files Browse the repository at this point in the history
The view and surface of permanent outputs were not correctly released
when reloading an experiment. Make sure they are now.
  • Loading branch information
AlexisDrogoul committed Dec 19, 2021
1 parent 22d0d88 commit ddd2907
Show file tree
Hide file tree
Showing 2 changed files with 141 additions and 44 deletions.
141 changes: 112 additions & 29 deletions msi.gama.core/src/msi/gama/outputs/LayeredDisplayOutput.java
@@ -1,12 +1,12 @@
/*******************************************************************************************************
*
* msi.gama.outputs.LayeredDisplayOutput.java, in plugin msi.gama.core, is part of the source code of the GAMA modeling
* and simulation platform (v. 1.8.1)
* LayeredDisplayOutput.java, in msi.gama.core, is part of the source code of the
* GAMA modeling and simulation platform (v.1.8.2).
*
* (c) 2007-2020 UMI 209 UMMISCO IRD/SU & Partners
* (c) 2007-2021 UMI 209 UMMISCO IRD/SU & Partners (IRIT, MIAT, TLU, CTU)
*
* Visit https://github.com/gama-platform/gama for license information and contacts.
*
*
********************************************************************************************************/
package msi.gama.outputs;

Expand Down Expand Up @@ -301,15 +301,25 @@
isExecutable = false) }) })
public class LayeredDisplayOutput extends AbstractDisplayOutput {

/** The layers. */
private final List<AbstractLayerStatement> layers;

/** The surface. */
protected IDisplaySurface surface;

/** The index. */
private int index;

/** The data. */
private final LayeredDisplayData data = new LayeredDisplayData();
// private final ThreadLocal<LayeredDisplayData> data = ThreadLocal.withInitial(LayeredDisplayData::new);
/** The overlay info. */
// Specific to overlays
OverlayStatement overlayInfo;

/**
* The Class DisplaySerializer.
*/
public static class DisplaySerializer extends SymbolSerializer<SymbolDescription> {

/**
Expand All @@ -336,6 +346,9 @@ public static class DisplaySerializer extends SymbolSerializer<SymbolDescription

}

/**
* The Class InfoValidator.
*/
public static class InfoValidator implements IDescriptionValidator<IDescription> {

/**
Expand Down Expand Up @@ -399,6 +412,12 @@ public void validate(final IDescription d) {
d.removeFacets("camera_pos", "camera_look_pos", "camera_up_vector");
}

/**
* Handle inheritance.
*
* @param d the d
* @param string the string
*/
private void handleInheritance(final IDescription d, final String string) {
final IDescription output = d.getEnclosingDescription();
for (final IDescription display : output.getChildrenWithKeyword(DISPLAY)) {
Expand All @@ -410,6 +429,12 @@ private void handleInheritance(final IDescription d, final String string) {
d.error("No parent display named '" + string + "' found");
}

/**
* Handle inheritance.
*
* @param child the child
* @param parent the parent
*/
private void handleInheritance(final IDescription child, final IDescription parent) {
final Facets childFacets = child.getFacets();
final boolean hasVirtual = childFacets.containsKey(VIRTUAL);
Expand All @@ -422,16 +447,24 @@ private void handleInheritance(final IDescription child, final IDescription pare

}

/**
* Instantiates a new layered display output.
*
* @param desc the desc
*/
public LayeredDisplayOutput(final IDescription desc) {
super(desc);

if (hasFacet(IKeyword.TYPE)) { getData().setDisplayType(getLiteral(IKeyword.TYPE)); }
layers = new ArrayList<>();
}

public IOverlayProvider<OverlayInfo> getOverlayProvider() {
return overlayInfo;
}
/**
* Gets the overlay provider.
*
* @return the overlay provider
*/
public IOverlayProvider<OverlayInfo> getOverlayProvider() { return overlayInfo; }

@Override
public boolean shouldOpenAsynchronously() {
Expand Down Expand Up @@ -488,6 +521,11 @@ public void dispose() {
getData().dispose();
}

/**
* Creates the surface.
*
* @param scope the scope
*/
protected void createSurface(final IScope scope) {
if (surface != null) {
surface.outputReloaded();
Expand All @@ -509,14 +547,15 @@ public String getViewId() {
return IGui.LAYER_VIEW_ID;
}

public IDisplaySurface getSurface() {
return surface;
}
/**
* Gets the surface.
*
* @return the surface
*/
public IDisplaySurface getSurface() { return surface; }

@Override
public List<? extends ISymbol> getChildren() {
return getLayers();
}
public List<? extends ISymbol> getChildren() { return getLayers(); }

@Override
public void setChildren(final Iterable<? extends ISymbol> commands) {
Expand All @@ -532,27 +571,52 @@ public void setChildren(final Iterable<? extends ISymbol> commands) {

}

/**
* Sets the surface.
*
* @param surface the new surface
*/
public void setSurface(final IDisplaySurface surface) {
this.surface = surface;
if (surface == null) { view = null; }
}

/**
* Gets the image.
*
* @return the image
*/
public BufferedImage getImage() {
return surface == null ? null : surface.getImage(surface.getWidth(), surface.getHeight());
}

/**
* Gets the image.
*
* @param w the w
* @param h the h
* @return the image
*/
public BufferedImage getImage(final int w, final int h) {
return surface == null ? null : surface.getImage(w, h);
}

/**
* Sets the layers.
*
* @param layers the new layers
*/
public void setLayers(final List<AbstractLayerStatement> layers) {
this.layers.clear();
this.layers.addAll(layers);
}

public List<AbstractLayerStatement> getLayers() {
return layers;
}
/**
* Gets the layers.
*
* @return the layers
*/
public List<AbstractLayerStatement> getLayers() { return layers; }

@Override
public void setPaused(final boolean paused) {
Expand All @@ -563,6 +627,11 @@ public void setPaused(final boolean paused) {
if (wasPaused && !paused) { surface.updateDisplay(false); }
}

/**
* Gets the data.
*
* @return the data
*/
public LayeredDisplayData getData() {
return data; // .get();
}
Expand All @@ -579,17 +648,21 @@ public void setSynchronized(final boolean sync) {
}

@Override
public boolean isSynchronized() {
return super.isSynchronized() && getData().isSynchronized();
}

public int getIndex() {
return index;
}

public void setIndex(final int index) {
this.index = index;
}
public boolean isSynchronized() { return super.isSynchronized() && getData().isSynchronized(); }

/**
* Gets the index.
*
* @return the index
*/
public int getIndex() { return index; }

/**
* Sets the index.
*
* @param index the new index
*/
public void setIndex(final int index) { this.index = index; }

@Override
public boolean isAutoSave() {
Expand All @@ -598,6 +671,11 @@ public boolean isAutoSave() {
return true;
}

/**
* Zoom.
*
* @param mode the mode
*/
public void zoom(final int mode) {
if (mode < 0) {
surface.zoomOut();
Expand All @@ -609,8 +687,13 @@ public void zoom(final int mode) {
}

@Override
public IGamaView.Display getView() {
return (Display) super.getView();
public IGamaView.Display getView() { return (Display) super.getView(); }

/**
* Release view.
*/
public void releaseView() {
view = null;
}

}
Expand Up @@ -287,6 +287,8 @@ public void widgetDisposed(final DisposeEvent e) {
s.dispose();
output.setSurface(null);
}
output.releaseView();
output.setSurface(null);
}

disposed = true;
Expand All @@ -299,7 +301,11 @@ public void widgetDisposed(final DisposeEvent e) {
}
synchronizer.authorizeViewUpdate();
// }
if (updateThread != null) { updateThread.interrupt(); }
if (updateThread != null) {
updateThread.interrupt();
DEBUG.OUT("Update thread disposed for " + getTitle());
updateThread = null;
}
if (decorator != null) { decorator.dispose(); }
super.widgetDisposed(e);
}
Expand Down Expand Up @@ -358,24 +364,32 @@ public IStatus runInUIThread(final IProgressMonitor monitor) {
}

/** The update thread. */
final Thread updateThread = new Thread(() -> {
final IDisplaySurface surface = getDisplaySurface();
synchronizer.waitForSurfaceToBeRealized();
while (!disposed && !surface.isDisposed()) {
try {
synchronizer.waitForViewUpdateAuthorisation();
surface.updateDisplay(false);
if (surface.getData().isAutosave()) { takeSnapshot(); }
inInitPhase = false;
} catch (Exception e) {
DEBUG.OUT("Error when updating " + this.getTitle() + ": " + e.getMessage());
Thread updateThread;

/**
* Inits the update thread.
*/
private void initUpdateThread() {
updateThread = new Thread(() -> {
final IDisplaySurface surface = getDisplaySurface();
synchronizer.waitForSurfaceToBeRealized();
while (!disposed && !surface.isDisposed()) {
try {
synchronizer.waitForViewUpdateAuthorisation();
surface.updateDisplay(false);
if (surface.getData().isAutosave()) { takeSnapshot(); }
inInitPhase = false;
} catch (Exception e) {
DEBUG.OUT("Error when updating " + this.getTitle() + ": " + e.getMessage());
}
}
}
});
});
}

@Override
public void update(final IDisplayOutput out) {
if (!updateThread.isAlive()) {
if (updateThread == null || !updateThread.isAlive()) {
initUpdateThread();
synchronizer.setSurface(getDisplaySurface());
updateThread.start();
}
Expand Down

0 comments on commit ddd2907

Please sign in to comment.