[concurrency-interest] CopyOnWriteArrayList and snapshots

David M. Lloyd david.lloyd at redhat.com
Wed Mar 25 13:10:56 EDT 2009


I've run into a minor issue with CopyOnWriteArrayList and have come up with 
a simple solution for it.  The issue is that you want to perform more than 
one operation on the list (for instance, a size() followed by a get() with 
index, which is otherwise not terribly useful on this class), and you need 
the operations to be consistent with one another.  Using an iterator does 
provide some ability to do this kind of thing, since it works on an 
immutable snapshot of the array, but of course you are then limited to the 
basic iterator operations, which do not include random access.  You can get 
a copy of a snapshot using toArray(), but I thought it would be handy to 
have a more generalized snapshot() method which doesn't do a copy of all 
the list data.

Here's a simple five-minute patch which adds a snapshot() method, which 
returns an immutable List based on the array as it was.  Thoughts?

diff -r dde3fe2e8164 
src/share/classes/java/util/concurrent/CopyOnWriteArrayList.java
--- a/src/share/classes/java/util/concurrent/CopyOnWriteArrayList.java	Wed 
Feb 25 14:32:01 2009 +0000
+++ b/src/share/classes/java/util/concurrent/CopyOnWriteArrayList.java	Wed 
Mar 25 11:11:19 2009 -0500
@@ -988,6 +988,44 @@
          return new COWIterator<E>(elements, index);
      }

+    /**
+     * Returns a snapshot view of this list.  The returned list provides
+     * a snapshot of the state of the list when the method was called.  No
+     * synchronization is needed while calling the list methods.  The list
+     * is read-only; any methods which modify the state of the list will
+     * throw <tt>UnsupportedOperationException</tt>.
+     *
+     * @return a snapshot of this list
+     */
+    public List<E> snapshot() {
+        final Object[] snapshot = getArray();
+        return new AbstractList<E>() {
+            public E get(final int index) {
+                return CopyOnWriteArrayList.this.get(snapshot, index);
+            }
+
+            public int size() {
+                return snapshot.length;
+            }
+
+            public Iterator<E> iterator() {
+                return new COWIterator<E>(snapshot, 0);
+            }
+
+            public ListIterator<E> listIterator() {
+                return new COWIterator<E>(snapshot, 0);
+            }
+
+            public ListIterator<E> listIterator(final int index) {
+                Object[] elements = snapshot;
+                int len = elements.length;
+                if (index<0 || index>len)
+                    throw new IndexOutOfBoundsException("Index: "+index);
+                return new COWIterator<E>(elements, index);
+            }
+        };
+    }
+
      private static class COWIterator<E> implements ListIterator<E> {
          /** Snapshot of the array **/
          private final Object[] snapshot;


More information about the Concurrency-interest mailing list