Dennis Reedy (JIRA) wrote:
Dennis Reedy created RIVER-417:
----------------------------------

             Summary: com.sun.jini.outrigger.FastList fails to compile using 
Java 7
                 Key: RIVER-417
                 URL: https://issues.apache.org/jira/browse/RIVER-417
             Project: River
          Issue Type: Bug
            Reporter: Dennis Reedy


Inner class Node has private properties that are accessed by inner class 
FastListIteratorImpl

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira


Are you sure?  Which version?

package com.sun.jini.outrigger;

import java.util.Iterator;
import java.util.NoSuchElementException;
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
* java.util.concurrent.ConcurrentLinkedQueue.
*
* 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, 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.
        */
       synchronized boolean remove() {
           if (removed) {
               return false;
           }
           removed = true;
           return true;
       }

       synchronized void markOnList(FastList<?> list) {
           setList(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;
       }

       /**
        * @return the index
        */
       long getIndex() {
           return index;
       }

       /**
        * @param index the index to set
        */
       void setIndex(long index) {
           this.index = index;
       }

       /**
        * @return the list
        */
       FastList<?> getList() {
           return list;
       }

       /**
        * @param list the list to set
        */
       void setList(FastList<?> list) {
           this.list = list;
       }
   }

   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.getIndex() >= 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.getList() == null) {
               node.setList(this);
           } else {
               throw new IllegalArgumentException("Attempt to reuse node "
                       + node);
           }
       }
       node.setIndex(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.getList() != 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.getIndex() >= 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();
   }
/**
    * Iterator that includes all physically present items,
    * regardless of when they were added or whether they have
    * been logically removed. This method is intended for
    * testing. For example, it can be used to verify
    * that a reap() call does in fact physically remove
    * the items it should remove.
    *
    * @return
    */
   Iterator<T> rawIterator() {
       return baseQueue.iterator();
   }

}

Reply via email to