Author: pats
Date: Mon Feb  7 02:17:39 2011
New Revision: 1067845

URL: http://svn.apache.org/viewvc?rev=1067845&view=rev
Log:
Minor changes and comments.

Modified:
    
incubator/river/jtsk/skunk/patsOutrigger/src/com/sun/jini/outrigger/FastList.java

Modified: 
incubator/river/jtsk/skunk/patsOutrigger/src/com/sun/jini/outrigger/FastList.java
URL: 
http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/patsOutrigger/src/com/sun/jini/outrigger/FastList.java?rev=1067845&r1=1067844&r2=1067845&view=diff
==============================================================================
--- 
incubator/river/jtsk/skunk/patsOutrigger/src/com/sun/jini/outrigger/FastList.java
 (original)
+++ 
incubator/river/jtsk/skunk/patsOutrigger/src/com/sun/jini/outrigger/FastList.java
 Mon Feb  7 02:17:39 2011
@@ -6,183 +6,258 @@ import java.util.Queue;
 import java.util.concurrent.ConcurrentLinkedQueue;
 import java.util.concurrent.atomic.AtomicLong;
 
-
 /**
  * Simplified list for rapid append, removal, and scanning from multiple
  * threads. It is intended as a substitute for the previous FastList, but uses
  * an Iterator rather than limiting a thread to a single scan at a time.
  * 
- * This version is completely rewritten, based on 
+ * This version is completely rewritten, based on
  * java.util.concurrent.ConcurrentLinkedQueue.
  * 
- * @param <T> Node type, required to extend FastList.Node so that the
- * FastList can keep working data for each Node without using mapping or extra
- * data structures.
+ * It provides two features in addition to those of ConcurrentLinkedQueue:
+ * 
+ * 1. Fast logical removal of a Node from the middle of the list. The node is
+ * merely marked as removed. It will be physically removed during a reap, or 
any
+ * Iterator scan that reaches it after it is marked.
+ * 
+ * 2. Guaranteed finite scans. If a node is added strictly after construction 
of
+ * an Iterator, it will not be shown by the Iterator.
+ * 
+ * Concurrency: A FastList object can be freely accessed by multiple threads
+ * without synchronization. Within a thread, the implementation synchronizes
+ * on at most one node at a time. Conventionally, a caller who synchronizes on 
+ * more than one node must do so in order of appearance in the list. While
+ * synchronized on the FastList object, a caller must not synchronize on 
+ * any FastList node or call any FastList method.
+ * 
+ * The Iterator returned by iterator() is not multi-thread safe. Callers
+ * must ensure it is accessed by at most one thread at a time, and that
+ * all actions on it in one thread happen-before any actions in a later
+ * thread.
+ * 
+ * @param <T>
+ *            Node type, required to extend FastList.Node so that the FastList
+ *            can keep working data for each Node without using mapping or 
extra
+ *            data structures.
  */
 class FastList<T extends FastList.Node> implements Iterable<T> {
 
-
-       /**
-        * The type parameter for the FastList must extend this type, and
-        * all nodes added to the list are of that parameter type.
-        * 
-        * A node can be added to a list at most once. Any attempt to add it 
again
-        * will result in an IllegalStateException.
-        * 
-        */
-       static class Node {
-               /**
-                * True if this node has been removed from its list.
-                */
-               private volatile boolean removed;
-               /**
-                * This node does not need to be shown to scans
-                * with index greater than or equal to this index.
-                */
-               private volatile long index;
-               @SuppressWarnings("unchecked")
-               private FastList list;
-               
-
-               /**
-                * Remove this node from its list.
-                * 
-                * @return true if this node has never previously been removed 
false if
-                *         it has already been removed.
-                */
-               private synchronized boolean remove() {
-                       if (removed) {
-                               return false;
-                       }
-                       removed = true;
-                       return true;
-               }
-
-               @SuppressWarnings("unchecked")
-               synchronized void markOnList(FastList list) {
-                       this.list = list;
-               }
-
-               /**
-                * Report whether the node has been removed. If the result is 
true the
-                * node has definitely been removed. If it is false, the node 
may still
-                * have been removed. To get a fully reliable result, 
synchronize on the
-                * node.
-                */
-               public boolean removed() {
-                       return removed;
-               }
-       }
-
-       interface FastListIterator<T> extends Iterator<T> {
-               boolean lastRemoveSucceeded();
-       }
-
-
-       private class FastListIteratorImpl implements Iterator<T> {
-               private T removable;
-               private T next;
-               private final long index;
-               private final Iterator<T> baseIterator;
-
-               private FastListIteratorImpl(long index) {
-                       this.index = index;
-                       baseIterator = baseQueue.iterator();
-                       next = getNext();
-               }
-
-
-               public boolean hasNext() {
-                       return next != null;
-               }
-
-               public T next() {
-                       if (!hasNext()) {
-                               throw new NoSuchElementException();
-                       }
-
-                       removable = next;
-                       next = getNext();
-                       return removable;
-               }
-
-               public void remove() {
-                       if (removable != null) {
-                               removable.remove();
-                               removable = null;
-                       } else {
-                               throw new IllegalStateException();
-                       }
-               }
-
-               /**
-                * Find the next eligible node, null if there is none.
-                * skip over removed nodes, and 
-                * @return
-                */
-               private T getNext(){
-                       T node = null;
-                       while(baseIterator.hasNext()){
-                               node = baseIterator.next();
-                               if(node.removed()){
-                                       /* Tell the base list to drop it */
-                                       baseIterator.remove();
-                               }
-                               if(node.index >= index){
-                                       /* Seen all the relevant nodes. */
-                                       node = null;
-                                       break;
-                               }
-                               if(!node.removed()){
-                                       /* Got a keeper. */
-                                       break;
-                               }
-                       }
-                       return node;
-               }
-       }
-
-
-       private final AtomicLong index = new AtomicLong(Long.MIN_VALUE);
-       private final Queue<T> baseQueue = new ConcurrentLinkedQueue<T>();
-
-       /**
-        * Add a node to the tail of the list.
-        * @param node Each node can only be added once, regardless of removal.
-        * @throws IllegalArgumentException The node has been added to a list 
previously.
-        */
-       public void add(T node) {
-               synchronized (node) {
-                       if (node.list == null) {
-                               node.list = this;
-                       } else {
-                               throw new IllegalArgumentException("Attempt to 
reuse node "
-                                               + node);
-                       }
-               }
-               node.index = index.getAndIncrement();
-               baseQueue.add(node);
-       }
-       
-       public boolean remove(T node){
-               if(node.list != this){
-                       throw new IllegalArgumentException("Cannot remove a 
node from a list it is not on");
-               }
-               return node.remove();
-       }
-
-       public void reap() {
-               Iterator<T> it = baseQueue.iterator();
-               while(it.hasNext()){
-                       T node = it.next();
-                       if(node.removed()){
-                               it.remove();
-                       }
-               }
-       }
-       
-       public Iterator<T> iterator(){
-               return new FastListIteratorImpl(index.get());
-       }
+    /**
+     * The type parameter for the FastList, T, must extend this type, and all
+     * nodes added to the list are of type T.
+     * 
+     * A node can be added to a list at most once. Any attempt to add it again
+     * will result in an IllegalStateException.
+     * 
+     */
+    static class Node {
+        /**
+         * True if this node has been removed from its list. Protected by
+         * synchronization on the Node when an exact answer is needed, but 
often
+         * checked without synchronization to skip work of the Node is reported
+         * as removed. Transitions only from false to true.
+         */
+        private volatile boolean removed;
+        /**
+         * This node does not need to be shown to scans with index greater than
+         * or equal to this index.
+         */
+        private volatile long index;
+
+        /**
+         * null until the node is added to a list, then a reference to the 
list.
+         * Once added to a list, it cannot be added to another. It can only be
+         * removed from the list to which it was added. Protected by
+         * synchronization on the node.
+         */
+        private FastList<?> list;
+
+        /**
+         * Remove this node from its list.
+         * 
+         * @return true if this node has never previously been removed, false 
if
+         *         it has already been removed.
+         */
+        private synchronized boolean remove() {
+            if (removed) {
+                return false;
+            }
+            removed = true;
+            return true;
+        }
+
+        synchronized void markOnList(FastList<?> list) {
+            this.list = list;
+        }
+
+        /**
+         * Report whether the node has been removed. If the result is true the
+         * node has definitely been removed. If it is false, the node may still
+         * have been removed. To get a fully reliable result, synchronize on 
the
+         * node.
+         */
+        public boolean removed() {
+            return removed;
+        }
+    }
+
+    private class FastListIteratorImpl implements Iterator<T> {
+        /* The last node returned as a next() result, null
+         * if there is none, or it has already been removed.
+         */
+        private T removable;
+        /* The node to be returned by the next call to next().*/
+        private T next;
+        /* Index of the first node added after this iterator's construction. */
+        private final long index;
+        /* Iterator over the underlying ConcurrentLinkedQueue.*/
+        private final Iterator<T> baseIterator;
+
+        private FastListIteratorImpl() {
+            index = nextIndex.get();
+            baseIterator = baseQueue.iterator();
+            next = getNext();
+        }
+
+        public boolean hasNext() {
+            return next != null;
+        }
+
+        public T next() {
+            if (!hasNext()) {
+                throw new NoSuchElementException();
+            }
+
+            removable = next;
+            next = getNext();
+            return removable;
+        }
+
+        public void remove() {
+            if (removable != null) {
+                removable.remove();
+                removable = null;
+            } else {
+                throw new IllegalStateException();
+            }
+        }
+
+        /**
+         * Find the next eligible node, null if there is none. skip over 
removed
+         * nodes, and stop on reaching a Node that was added after this scan
+         * started.
+         * 
+         * @return The next eligible node, null if there is none.
+         */
+        private T getNext() {
+            T result = null;
+            while (baseIterator.hasNext()) {
+                T node = baseIterator.next();
+                if (node.index >= index) {
+                    /* Finished, no appropriate nodes.*/
+                    break;
+                }
+                if (node.removed()) {
+                    /* Tell the base list to drop it */
+                    baseIterator.remove();
+                } else {
+                    /* Found a node to return. */
+                    result = node;
+                    break;
+                }
+            }
+            return result;
+        }
+    }
+
+    /**
+     * The next index, a modified form of timestamp. Each Node is assigned a
+     * strictly increasing index on being added to a FastList. Each Iterator
+     * scan stops (hasNext() false) when it reaches a Node that has an index at
+     * least as high as the value of nextIndex when the Iterator was created.
+     * This ensures finite scan lengths, even if nodes are being added
+     * continuously during the scan.
+     */
+    private final AtomicLong nextIndex = new AtomicLong(0);
+
+    /**
+     * The underlying queue.
+     */
+    private final Queue<T> baseQueue = new ConcurrentLinkedQueue<T>();
+
+    /**
+     * Add a node to the tail of the list.
+     * 
+     * @param node
+     *            Each node can only be added once, regardless of removal.
+     * @throws IllegalArgumentException
+     *             The node has been added to a list previously.
+     */
+    public void add(T node) {
+        synchronized (node) {
+            if (node.list == null) {
+                node.list = this;
+            } else {
+                throw new IllegalArgumentException("Attempt to reuse node "
+                        + node);
+            }
+        }
+        node.index = nextIndex.getAndIncrement();
+        baseQueue.add(node);
+    }
+
+    /**
+     * Remove the node.
+     * 
+     * @param node
+     * @return true if this is the first remove call for this node, false if 
the
+     *         node has already been removed.
+     * @throws IllegalArgumentException
+     *             The node has not been added to this FastList.
+     */
+    public boolean remove(T node) {
+        synchronized (node) {
+            if (node.list != this) {
+                throw new IllegalArgumentException(
+                        "Cannot remove a node from a list it is not on");
+            }
+            return node.remove();
+        }
+    }
+
+    /**
+     * Scan the list, physically removing nodes that have already been 
logically
+     * removed.
+     */
+    public void reap() {
+        long stopIndex = nextIndex.get();
+        Iterator<T> it = baseQueue.iterator();
+        while (it.hasNext()) {
+            T node = it.next();
+            if (node.index >= stopIndex) {
+                // Done enough
+                return;
+            }
+            if (node.removed()) {
+                it.remove();
+            }
+        }
+    }
+
+    /*
+     * The returned Iterator returns all elements that were
+     * added to the FastList, and not removed, before the iterator() call.
+     * It will return no elements that were added after the iterator() call
+     * returned. Elements that were added in parallel with the iterator()
+     * call may be returned, depending on exact timing.
+     * 
+     * It makes reasonable efforts to avoid returning removed elements, but
+     * only a synchronized check can guaranteed up-to-date removal information.
+     * (non-Javadoc)
+     * @see java.lang.Iterable#iterator()
+     */
+    public Iterator<T> iterator() {
+        return new FastListIteratorImpl();
+    }
 
 }


Reply via email to