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
commit b0405ddc77b3e50a2636d03f4bd91f1bfaee519b
Author: Martin Desruisseaux <martin.desruisseaux@geomatys.com>
AuthorDate: Wed Jul 1 13:05:20 2020 +0200
Provides a mechanism for creating transforms without caching them.
It can improve performances when creating a lot of transforms living for a short time.
---
.../internal/referencing/provider/Providers.java | 2 +
.../transform/DefaultMathTransformFactory.java | 88 ++++++++++++++++++++--
.../transform/DefaultMathTransformFactoryTest.java | 15 ++++
3 files changed, 100 insertions(+), 5 deletions(-)
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Providers.java
b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Providers.java
index 8176e21..6ed48e5 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Providers.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Providers.java
@@ -19,6 +19,7 @@ package org.apache.sis.internal.referencing.provider;
import java.util.List;
import org.opengis.referencing.operation.OperationMethod;
import org.apache.sis.internal.referencing.LazySet;
+import org.apache.sis.util.Workaround;
/**
@@ -34,6 +35,7 @@ import org.apache.sis.internal.referencing.LazySet;
* @since 0.7
* @module
*/
+@Workaround(library="JDK", version="1.8")
public final class Providers extends LazySet<OperationMethod> {
/**
* Creates new set of provider.
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java
b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java
index c07fbfa..f84d11d 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java
@@ -163,7 +163,7 @@ import org.apache.sis.util.resources.Errors;
* There is typically only one {@code MathTransformFactory} instance for the whole application.
*
* @author Martin Desruisseaux (Geomatys, IRD)
- * @version 0.8
+ * @version 1.1
*
* @see MathTransformProvider
* @see AbstractMathTransform
@@ -227,8 +227,9 @@ public class DefaultMathTransformFactory extends AbstractFactory implements
Math
private final ThreadLocal<OperationMethod> lastMethod;
/**
- * The math transforms created so far. This pool is used in order
- * to return instances of existing math transforms when possible.
+ * The math transforms created so far. This pool is used in order to return instances
of existing
+ * math transforms when possible. If {@code null}, then no pool should be used. A null
value is
+ * preferable when the transforms are known to be short-lived, for avoiding the cost
of caching them.
*/
private final WeakHashSet<MathTransform> pool;
@@ -240,6 +241,13 @@ public class DefaultMathTransformFactory extends AbstractFactory implements
Math
private final AtomicReference<Parser> parser;
/**
+ * The factory with opposite caching factory, or {@code null} if not yet created.
+ *
+ * @see #caching(boolean)
+ */
+ private DefaultMathTransformFactory oppositeCachingPolicy;
+
+ /**
* Creates a new factory which will discover operation methods with a {@link ServiceLoader}.
* The {@link OperationMethod} implementations shall be listed in the following file:
*
@@ -313,6 +321,74 @@ public class DefaultMathTransformFactory extends AbstractFactory implements
Math
}
/**
+ * Creates a new factory with the same configuration than given factory but without caching.
+ */
+ private DefaultMathTransformFactory(final DefaultMathTransformFactory parent) {
+ methods = parent.methods;
+ methodsByName = parent.methodsByName;
+ methodsByType = parent.methodsByType;
+ lastMethod = new ThreadLocal<>();
+ pool = null;
+ parser = parent.parser;
+ oppositeCachingPolicy = parent;
+ }
+
+ /**
+ * Returns a factory for the same transforms than this factory, but with caching potentially
disabled.
+ * By default, {@code DefaultMathTransformFactory} caches the {@link MathTransform} instances
for sharing
+ * existing instances when transforms are created many times with the same set of parameters.
+ * However this caching may be unnecessarily costly when the transforms to create are
known to be short lived.
+ * This method allows to get a factory better suited for short-lived objects.
+ *
+ * <p>This method does not modify the state of this factory. Instead different
factory instances for the
+ * different caching policy are returned.</p>
+ *
+ * @param enabled whether caching should be enabled.
+ * @return a factory for the given caching policy.
+ *
+ * @since 1.1
+ */
+ public DefaultMathTransformFactory caching(final boolean enabled) {
+ if (enabled) {
+ return this;
+ }
+ synchronized (this) {
+ if (oppositeCachingPolicy == null) {
+ oppositeCachingPolicy = new NoCache(this);
+ }
+ return oppositeCachingPolicy;
+ }
+ }
+
+ /**
+ * Accessor for {@link NoCache} implementation.
+ */
+ final DefaultMathTransformFactory oppositeCachingPolicy() {
+ return oppositeCachingPolicy;
+ }
+
+ /**
+ * A factory performing no caching.
+ * This factory shares the same operation methods than the parent factory.
+ */
+ private static final class NoCache extends DefaultMathTransformFactory {
+ /** Creates a new factory with the same configuration than given factory. */
+ NoCache(final DefaultMathTransformFactory parent) {
+ super(parent);
+ }
+
+ /** Returns a factory for the same transforms but given caching policy. */
+ @Override public DefaultMathTransformFactory caching(final boolean enabled) {
+ return enabled ? oppositeCachingPolicy() : this;
+ }
+
+ /** Notifies parent factory that the set of operation methods may have changed. */
+ @Override public void reload() {
+ oppositeCachingPolicy().reload();
+ }
+ }
+
+ /**
* Returns a set of available methods for coordinate operations of the given type.
* The {@code type} argument can be used for filtering the kind of operations described
by the returned
* {@code OperationMethod}s. The argument is usually (but not restricted to) one of the
following types:
@@ -1417,7 +1493,7 @@ public class DefaultMathTransformFactory extends AbstractFactory implements
Math
* Replaces the given transform by a unique instance, if one already exists.
*/
private MathTransform unique(final MathTransform tr) {
- return pool.unique(tr);
+ return (pool != null) ? pool.unique(tr) : tr;
}
/**
@@ -1467,7 +1543,9 @@ public class DefaultMathTransformFactory extends AbstractFactory implements
Math
c.reset();
}
}
- pool.clear();
+ if (pool != null) {
+ pool.clear();
+ }
}
}
}
diff --git a/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactoryTest.java
b/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactoryTest.java
index cc4ab05..6d5092b 100644
--- a/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactoryTest.java
+++ b/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactoryTest.java
@@ -279,4 +279,19 @@ public final strictfp class DefaultMathTransformFactoryTest extends TestCase
{
assertEquals(classification, projection.getMethod().getName().getCode());
}
}
+
+ /**
+ * Tests {@link DefaultMathTransformFactory#caching(boolean)}.
+ */
+ @Test
+ public void testCaching() {
+ final DefaultMathTransformFactory mtFactory = DefaultFactories.forBuildin(
+ MathTransformFactory.class, DefaultMathTransformFactory.class);
+ final DefaultMathTransformFactory caching = mtFactory.caching(false);
+
+ assertNotSame(mtFactory, caching);
+ assertSame (mtFactory, mtFactory.caching(true));
+ assertSame (mtFactory, caching.caching(true));
+ assertSame (caching, caching.caching(false));
+ }
}
|