This is an automated email from the ASF dual-hosted git repository.
desruisseaux pushed a commit to branch geoapi-4.0
in repository https://gitbox.apache.org/repos/asf/sis.git
The following commit(s) were added to refs/heads/geoapi-4.0 by this push:
new e2fb98c Prevent having many threads requesting the same tile.
e2fb98c is described below
commit e2fb98caff0f4ff79fbce8e26fd21bc431284f27
Author: Martin Desruisseaux <[email protected]>
AuthorDate: Sat Jan 25 19:10:04 2020 +0100
Prevent having many threads requesting the same tile.
---
.../java/org/apache/sis/gui/coverage/GridTile.java | 62 ++++++++++++++--------
.../java/org/apache/sis/gui/coverage/GridView.java | 4 +-
.../sis/internal/coverage/j2d/ImageUtilities.java | 7 +++
.../internal/coverage/j2d/ImageUtilitiesTest.java | 8 +++
4 files changed, 57 insertions(+), 24 deletions(-)
diff --git
a/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/GridTile.java
b/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/GridTile.java
index e9224d6..e9e2a4e 100644
---
a/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/GridTile.java
+++
b/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/GridTile.java
@@ -47,9 +47,15 @@ final class GridTile {
Raster tile;
/**
- * Whether an error occurred while reading the tile.
+ * Non-null if an error occurred while reading the tile.
*/
- boolean error;
+ Throwable error;
+
+ /**
+ * Whether a tile loading is in progress. Used for avoiding to create many
threads requesting the same tile.
+ * If loading is in progress, other requests for that tile will return
{@code null} immediately.
+ */
+ private boolean loading;
/**
* Creates a new tile for the given tile coordinates.
@@ -67,27 +73,41 @@ final class GridTile {
* @param view the view for which to load a tile.
*/
final void load(final GridView view) {
- final RenderedImage image = view.getImage();
- BackgroundThreads.execute(new Task<Raster>() {
- /** Invoked in background thread for fetching the tile. */
- @Override protected Raster call() {
- return image.getTile(tileX, tileY);
- }
+ if (!loading && error == null) {
+ loading = true;
+ final RenderedImage image = view.getImage();
+ BackgroundThreads.execute(new Task<Raster>() {
+ /** Invoked in background thread for fetching the tile. */
+ @Override protected Raster call() {
+ return image.getTile(tileX, tileY);
+ }
- /** Invoked in JavaFX thread on success. */
- @Override protected void succeeded() {
- super.succeeded();
- tile = getValue();
- error = false;
- view.contentChanged(false);
- }
+ /** Invoked in JavaFX thread on success. */
+ @Override protected void succeeded() {
+ super.succeeded();
+ tile = getValue();
+ error = null;
+ loading = false;
+ view.contentChanged(false);
+ }
- /** Invoked in JavaFX thread on failure. */
- @Override protected void failed() {
- super.failed();
- error = true;
- }
- });
+ /** Invoked in JavaFX thread on failure. */
+ @Override protected void failed() {
+ super.failed();
+ tile = null;
+ error = getException();
+ loading = false;
+ }
+
+ /** Invoked in JavaFX thread on cancellation. */
+ @Override protected void cancelled() {
+ super.cancelled();
+ tile = null;
+ error = null;
+ loading = false;
+ }
+ });
+ }
}
/**
diff --git
a/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/GridView.java
b/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/GridView.java
index 47e7c3b..ee5c8ca 100644
---
a/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/GridView.java
+++
b/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/GridView.java
@@ -17,7 +17,6 @@
package org.apache.sis.gui.coverage;
import java.util.Map;
-import java.util.Arrays;
import java.text.NumberFormat;
import java.text.FieldPosition;
import java.awt.image.Raster;
@@ -98,8 +97,7 @@ public class GridView extends Control {
* since "real" caching is done by {@link
org.apache.sis.image.ComputedImage}. The purpose of this cache is
* to remember that a tile is immediately available and that we do not
need to start a background thread.
*/
- private final Map<GridTile,GridTile> tiles = new BoundedHashMap<>(10 *
(1024 * 1024) /
- (ImageUtilities.DEFAULT_TILE_SIZE *
ImageUtilities.DEFAULT_TILE_SIZE));
+ private final Map<GridTile,GridTile> tiles = new
BoundedHashMap<>(ImageUtilities.SUGGESTED_TILE_CACHE_SIZE);
/**
* The most recently used tile. Cached separately because it will be the
desired tile in the vast majority
diff --git
a/core/sis-feature/src/main/java/org/apache/sis/internal/coverage/j2d/ImageUtilities.java
b/core/sis-feature/src/main/java/org/apache/sis/internal/coverage/j2d/ImageUtilities.java
index 6afdb3d..67f397b 100644
---
a/core/sis-feature/src/main/java/org/apache/sis/internal/coverage/j2d/ImageUtilities.java
+++
b/core/sis-feature/src/main/java/org/apache/sis/internal/coverage/j2d/ImageUtilities.java
@@ -53,6 +53,13 @@ public final class ImageUtilities extends Static {
public static final int DEFAULT_TILE_SIZE = 256;
/**
+ * Suggested size for a tile cache in number of tiles. This value can be
used for very simple caching mechanism,
+ * keeping the most recently used tiles up to 10 Mb of memory. This is not
for sophisticated caching mechanism;
+ * instead the "real" caching should be done by {@link
org.apache.sis.image.ComputedImage}.
+ */
+ public static final int SUGGESTED_TILE_CACHE_SIZE = 10 * (1024 * 1024) /
(DEFAULT_TILE_SIZE * DEFAULT_TILE_SIZE);
+
+ /**
* Approximate size of the buffer to use for copying data from/to a
raster, in bits.
* The actual buffer size may be smaller or larger, depending on the
actual tile size.
* This value does not need to be very large. The current value is 8 kb.
diff --git
a/core/sis-feature/src/test/java/org/apache/sis/internal/coverage/j2d/ImageUtilitiesTest.java
b/core/sis-feature/src/test/java/org/apache/sis/internal/coverage/j2d/ImageUtilitiesTest.java
index 456d57f..cc90055 100644
---
a/core/sis-feature/src/test/java/org/apache/sis/internal/coverage/j2d/ImageUtilitiesTest.java
+++
b/core/sis-feature/src/test/java/org/apache/sis/internal/coverage/j2d/ImageUtilitiesTest.java
@@ -40,6 +40,14 @@ import static org.junit.Assert.*;
*/
public final strictfp class ImageUtilitiesTest extends TestCase {
/**
+ * Verifies that {@link ImageUtilities#SUGGESTED_TILE_CACHE_SIZE} is
strictly positive.
+ */
+ @Test
+ public void verifySuggestedTileCacheSize() {
+ assertTrue(ImageUtilities.SUGGESTED_TILE_CACHE_SIZE >= 1);
+ }
+
+ /**
* Tests {@link ImageUtilities#getBounds(RenderedImage)} and {@link
ImageUtilities#clipBounds(RenderedImage, Rectangle)}.
*/
@Test