ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jsr166y/LinkedTransferQueue.java
(Generate patch)

Comparing jsr166/src/jsr166y/LinkedTransferQueue.java (file contents):
Revision 1.73 by dl, Tue Aug 17 18:30:33 2010 UTC vs.
Revision 1.79 by dl, Fri Sep 10 10:43:23 2010 UTC

# Line 322 | Line 322 | public class LinkedTransferQueue<E> exte
322       * situations in which we cannot guarantee to make node s
323       * unreachable in this way: (1) If s is the trailing node of list
324       * (i.e., with null next), then it is pinned as the target node
325 <     * for appends, so can only be removed later when other nodes are
325 >     * for appends, so can only be removed later after other nodes are
326       * appended. (2) We cannot necessarily unlink s given a
327       * predecessor node that is matched (including the case of being
328       * cancelled): the predecessor may already be unspliced, in which
# Line 344 | Line 344 | public class LinkedTransferQueue<E> exte
344       * When these cases arise, rather than always retraversing the
345       * entire list to find an actual predecessor to unlink (which
346       * won't help for case (1) anyway), we record a conservative
347 <     * estimate of possible unsplice failures (in "sweepVotes").  We
348 <     * trigger a full sweep when the estimate exceeds a threshold
349 <     * indicating the maximum number of estimated removal failures to
350 <     * tolerate before sweeping through, unlinking cancelled nodes
351 <     * that were not unlinked upon initial removal. We perform sweeps
352 <     * by the thread hitting threshold (rather than background threads
353 <     * or by spreading work to other threads) because in the main
354 <     * contexts in which removal occurs, the caller is already
355 <     * timed-out, cancelled, or performing a potentially O(n)
356 <     * operation (i.e., remove(x)), none of which are time-critical
357 <     * enough to warrant the overhead that alternatives would impose
358 <     * on other threads.
347 >     * estimate of possible unsplice failures (in "sweepVotes").
348 >     * We trigger a full sweep when the estimate exceeds a threshold
349 >     * ("SWEEP_THRESHOLD") indicating the maximum number of estimated
350 >     * removal failures to tolerate before sweeping through, unlinking
351 >     * cancelled nodes that were not unlinked upon initial removal.
352 >     * We perform sweeps by the thread hitting threshold (rather than
353 >     * background threads or by spreading work to other threads)
354 >     * because in the main contexts in which removal occurs, the
355 >     * caller is already timed-out, cancelled, or performing a
356 >     * potentially O(n) operation (e.g. remove(x)), none of which are
357 >     * time-critical enough to warrant the overhead that alternatives
358 >     * would impose on other threads.
359       *
360       * Because the sweepVotes estimate is conservative, and because
361       * nodes become unlinked "naturally" as they fall off the head of
# Line 428 | Line 428 | public class LinkedTransferQueue<E> exte
428          }
429  
430          /**
431 <         * Creates a new node. Uses relaxed write because item can only
432 <         * be seen if followed by CAS.
431 >         * Constructs a new node.  Uses relaxed write because item can
432 >         * only be seen after publication via casNext.
433           */
434          Node(Object item, boolean isData) {
435              UNSAFE.putObject(this, itemOffset, item); // relaxed write
# Line 877 | Line 877 | public class LinkedTransferQueue<E> exte
877      }
878  
879      /**
880 <     * Unlinks matched nodes encountered in a traversal from head.
880 >     * Unlinks matched (typically cancelled) nodes encountered in a
881 >     * traversal from head.
882       */
883      private void sweep() {
884          for (Node p = head, s, n; p != null && (s = p.next) != null; ) {
885 <            if (p == s)                    // stale
886 <                p = head;
886 <            else if (!s.isMatched())
885 >            if (!s.isMatched())
886 >                // Unmatched nodes are never self-linked
887                  p = s;
888              else if ((n = s.next) == null) // trailing node is pinned
889                  break;
890 +            else if (s == n)    // stale
891 +                // No need to also check for p == s, since that implies s == n
892 +                p = head;
893              else
894                  p.casNext(s, n);
895          }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines