svn commit: r889761 - /ofbiz/trunk/framework/base/src/org/ofbiz/base/util/collections/GenericMap.java

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

svn commit: r889761 - /ofbiz/trunk/framework/base/src/org/ofbiz/base/util/collections/GenericMap.java

doogie-3
Author: doogie
Date: Fri Dec 11 18:43:55 2009
New Revision: 889761

URL: http://svn.apache.org/viewvc?rev=889761&view=rev
Log:
Support ConcurrentModificationException for iterators.

Modified:
    ofbiz/trunk/framework/base/src/org/ofbiz/base/util/collections/GenericMap.java

Modified: ofbiz/trunk/framework/base/src/org/ofbiz/base/util/collections/GenericMap.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/base/src/org/ofbiz/base/util/collections/GenericMap.java?rev=889761&r1=889760&r2=889761&view=diff
==============================================================================
--- ofbiz/trunk/framework/base/src/org/ofbiz/base/util/collections/GenericMap.java (original)
+++ ofbiz/trunk/framework/base/src/org/ofbiz/base/util/collections/GenericMap.java Fri Dec 11 18:43:55 2009
@@ -19,10 +19,12 @@
 package org.ofbiz.base.util.collections;
 
 import java.io.Serializable;
+import java.util.ConcurrentModificationException;
 import java.util.Collection;
 import java.util.Iterator;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
 import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
 
 import org.ofbiz.base.util.Appender;
@@ -33,10 +35,28 @@
     private static final AtomicReferenceFieldUpdater<GenericMap, Set> keySetUpdater = AtomicReferenceFieldUpdater.newUpdater(GenericMap.class, Set.class, "keySet");
     private static final AtomicReferenceFieldUpdater<GenericMap, Set> entrySetUpdater = AtomicReferenceFieldUpdater.newUpdater(GenericMap.class, Set.class, "entrySet");
     private static final AtomicReferenceFieldUpdater<GenericMap, Collection> valuesUpdater = AtomicReferenceFieldUpdater.newUpdater(GenericMap.class, Collection.class, "values");
+    private static final AtomicIntegerFieldUpdater<GenericMap> modCountUpdater = AtomicIntegerFieldUpdater.newUpdater(GenericMap.class, "modCount");
 
     private volatile Set<K> keySet;
     private volatile Set<Map.Entry<K, V>> entrySet;
     private volatile Collection<V> values;
+    private volatile int modCount;
+
+    public int getModCount() {
+        return modCount;
+    }
+
+    protected void incrementModCount() {
+        modCountUpdater.getAndIncrement(this);
+    }
+
+    public final void clear() {
+        if (isEmpty()) return;
+        incrementModCount();
+        clearInternal();
+    }
+
+    protected abstract void clearInternal();
 
     public boolean containsValue(Object value) {
         return values().contains(value);
@@ -91,6 +111,19 @@
 
     protected abstract V get(Object key, boolean noteAccess);
 
+    protected abstract class GenericMapIterator<DEST> extends IteratorWrapper<DEST, Map.Entry<K, V>> {
+        private final int currentModCount = getModCount();
+
+        protected GenericMapIterator(boolean noteAccess) {
+            super(iterator(noteAccess));
+        }
+
+        protected boolean isValid(Map.Entry<K, V> src) {
+            if (currentModCount != getModCount()) throw new ConcurrentModificationException();
+            return true;
+        }
+    }
+
     public final Set<Map.Entry<K, V>> entrySet() {
         if (entrySet == null) {
             entrySetUpdater.compareAndSet(this, null, new GenericMapEntrySet<K, V, GenericMap<K, V>>(this) {
@@ -99,7 +132,17 @@
                 }
 
                 public Iterator<Map.Entry<K, V>> iterator(boolean noteAccess) {
-                    return GenericMap.this.iterator(noteAccess);
+                    return new GenericMapIterator<Map.Entry<K, V>>(noteAccess) {
+                        protected void noteRemoval(Map.Entry<K, V> dest, Map.Entry<K, V> src) {
+                            // No need to note the remove, the wrapped iterator does that for us
+                            // evictionPolicy.remove(evictionDeque, dest);
+                            // if (diskStore != null) diskStore.remove(dest);
+                        }
+
+                        protected Map.Entry<K, V> convert(Map.Entry<K, V> src) {
+                            return src;
+                        }
+                    };
                 }
             });
         }
@@ -116,7 +159,7 @@
                 }
 
                 public Iterator<K> iterator(boolean noteAccess) {
-                    return new IteratorWrapper<K, Map.Entry<K, V>>(GenericMap.this.iterator(noteAccess)) {
+                    return new GenericMapIterator<K>(noteAccess) {
                         protected void noteRemoval(K dest, Map.Entry<K, V> src) {
                             // No need to note the remove, the wrapped iterator does that for us
                             // evictionPolicy.remove(evictionDeque, dest);
@@ -137,7 +180,7 @@
         if (values == null) {
             valuesUpdater.compareAndSet(this, null, new GenericMapValues<K, V, GenericMap<K, V>>(this) {
                 public Iterator<V> iterator(boolean noteAccess) {
-                    return new IteratorWrapper<V, Map.Entry<K, V>>(GenericMap.this.iterator(noteAccess)) {
+                    return new GenericMapIterator<V>(noteAccess) {
                         protected void noteRemoval(V dest, Map.Entry<K, V> src) {
                             // No need to note the remove, the wrapped iterator does that for us
                             // evictionPolicy.remove(evictionDeque, src.getKey());
@@ -154,11 +197,19 @@
         return values;
     }
 
-    public void putAll(Map<? extends K, ? extends V> map) {
+    public final V remove(Object key) {
+        return removeInternal(key, true);
+    }
+
+    protected abstract V removeInternal(Object key, boolean incrementModCount);
+
+    public final void putAll(Map<? extends K, ? extends V> map) {
         putAllInternal(map);
     }
 
     private <KE extends K, VE extends V> void putAllInternal(Map<KE, VE> map) {
+        if (map.isEmpty()) return;
+        incrementModCount();
         Iterator<Map.Entry<KE, VE>> it;
         if (map instanceof GenericMap) {
             GenericMap<KE, VE> otherMap = UtilGenerics.cast(map);