sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1449726 - /sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/collection/Cache.java
Date Mon, 25 Feb 2013 14:41:46 GMT
Author: desruisseaux
Date: Mon Feb 25 14:41:46 2013
New Revision: 1449726

URL: http://svn.apache.org/r1449726
Log:
Port the 'setKeyCollisionAllowed(boolean)' method.

Modified:
    sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/collection/Cache.java

Modified: sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/collection/Cache.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/collection/Cache.java?rev=1449726&r1=1449725&r2=1449726&view=diff
==============================================================================
--- sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/collection/Cache.java
[UTF-8] (original)
+++ sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/collection/Cache.java
[UTF-8] Mon Feb 25 14:41:46 2013
@@ -176,6 +176,15 @@ public class Cache<K,V> extends Abstract
     private final boolean soft;
 
     /**
+     * {@code true} if different values may be assigned to the same key. This is usually
+     * an error, so the default {@code Cache} behavior is to thrown an exception in such
+     * case.
+     *
+     * @see #isKeyCollisionAllowed()
+     */
+    private volatile boolean isKeyCollisionAllowed;
+
+    /**
      * A view over the entries in the cache.
      */
     private transient Set<Entry<K,V>> entries;
@@ -509,6 +518,18 @@ public class Cache<K,V> extends Abstract
             @SuppressWarnings("unchecked")
             final Work work = (Work) value;
             if (work.lock.isHeldByCurrentThread()) {
+                if (isKeyCollisionAllowed()) {
+                    /*
+                     * Example of key collision: the EPSG database defines the CoordinateOperation
+                     * 8653 ("ED50 to WGS84" using polynomial equations).  The EPSG factory
sets a
+                     * lock for this code, then searches for OperationParameters associated
to this
+                     * operation. One of those parameters ("Bu0v4") has the same key (EPSG:8653).
+                     * So we get a key collision. If we ignore the second occurrence, its
value will
+                     * not be cached. This is okay since the value that we really want to
cache is
+                     * CoordinateOperation, which is associated to the first occurrence of
that key.
+                     */
+                    return new Simple<>(null);
+                }
                 throw new IllegalStateException(Errors.format(Errors.Keys.RecursiveCreateCallForKey_1,
key));
             }
             return work.new Wait();
@@ -610,7 +631,7 @@ public class Cache<K,V> extends Abstract
          */
         @Override
         public void putAndUnlock(final V result) throws IllegalStateException {
-            if (result != value) {
+            if (result != value && !isKeyCollisionAllowed()) {
                 throw new IllegalStateException(Errors.format(Errors.Keys.KeyCollision_1,
"<unknown>"));
             }
         }
@@ -721,7 +742,7 @@ public class Cache<K,V> extends Abstract
              */
             @Override
             public void putAndUnlock(final V result) throws IllegalStateException {
-                if (result != get()) {
+                if (result != get() && !isKeyCollisionAllowed()) {
                     throw new IllegalStateException(Errors.format(Errors.Keys.KeyCollision_1,
key));
                 }
             }
@@ -851,6 +872,40 @@ public class Cache<K,V> extends Abstract
     }
 
     /**
+     * Returns {@code true} if different values may be assigned to the same key.
+     * The default value is {@code false}.
+     *
+     * @return {@code true} if key collisions are allowed.
+     */
+    public boolean isKeyCollisionAllowed() {
+        return isKeyCollisionAllowed;
+    }
+
+    /**
+     * If set to {@code true}, different values may be assigned to the same key. This is
usually an
+     * error, so the default {@code Cache} behavior is to thrown an {@link IllegalStateException}
+     * in such cases, typically when {@link Handler#putAndUnlock(Object)} is invoked. However
in
+     * some cases we may want to relax this check. For example the EPSG database sometime
assigns
+     * the same key to different kind of objects.
+     *
+     * <p>If key collisions are allowed and two threads invoke {@link #lock(Object)}
concurrently
+     * for the same key, then the value to be stored in the map will be the one computed
by the
+     * first thread who got the lock. The value computed by any other concurrent thread will
be
+     * ignored by this {@code Cache} class. However those threads still return their computed
+     * values to their callers.</p>
+     *
+     * <p>This property can also be set in order to allow some recursivity. If during
the creation
+     * of an object, the program asks to this {@code Cache} for the same object (using the
same key),
+     * then the default {@code Cache} implementation will consider this situation as a key
collision
+     * unless this property has been set to {@code true}.</p>
+     *
+     * @param allowed {@code true} if key collisions should be allowed.
+     */
+    public void setKeyCollisionAllowed(final boolean allowed) {
+        isKeyCollisionAllowed = allowed;
+    }
+
+    /**
      * Computes an estimation of the cost of the given value. The default implementation
returns 1
      * in all cases. Subclasses should override this method if they have some easy way to
measure
      * the relative cost of value objects.



Mime
View raw message