ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/FutureTask.java
(Generate patch)

Comparing jsr166/src/main/java/util/concurrent/FutureTask.java (file contents):
Revision 1.80 by jsr166, Sat Jun 18 15:20:30 2011 UTC vs.
Revision 1.81 by jsr166, Sat Jun 18 18:31:52 2011 UTC

# Line 296 | Line 296 | public class FutureTask<V> implements Ru
296       * Removes and signals all waiting threads, and invokes done().
297       */
298      private void finishCompletion() {
299 <        WaitNode q;
300 <        while ((q = waiters) != null) {
299 >        for (WaitNode q; (q = waiters) != null;) {
300              if (UNSAFE.compareAndSwapObject(this, waitersOffset, q, null)) {
301                  for (;;) {
302                      Thread t = q.thread;
# Line 364 | Line 363 | public class FutureTask<V> implements Ru
363       * Tries to unlink a timed-out or interrupted wait node to avoid
364       * accumulating garbage.  Internal nodes are simply unspliced
365       * without CAS since it is harmless if they are traversed anyway
366 <     * by releasers. To avoid effects of unsplicing from already
367 <     * removed nodes, the list is retraversed until no cancelled nodes
368 <     * are found.  This is slow when there are a lot of nodes, but we
369 <     * don't expect lists to be long enough to outweigh
370 <     * higher-overhead schemes.
366 >     * by releasers.  To avoid effects of unsplicing from already
367 >     * removed nodes, the list is retraversed in case of an apparent
368 >     * race.  This is slow when there are a lot of nodes, but we don't
369 >     * expect lists to be long enough to outweigh higher-overhead
370 >     * schemes.
371       */
372      private void removeWaiter(WaitNode node) {
373          if (node != null) {
374              node.thread = null;
375 <            for (WaitNode pred = null, q = waiters; q != null;) {
376 <                WaitNode next = q.next;
377 <                if (q.thread != null) {
378 <                    pred = q;
379 <                    q = next;
380 <                }
381 <                else {
382 <                    if (pred != null)
383 <                        pred.next = next;
384 <                    else
385 <                        UNSAFE.compareAndSwapObject(this, waitersOffset,
386 <                                                    q, next);
387 <                    pred = null; // restart until clean sweep
388 <                    q = waiters;
375 >            retry:
376 >            for (;;) {          // restart on removeWaiter race
377 >                for (WaitNode pred = null, q = waiters, s; q != null; q = s) {
378 >                    s = q.next;
379 >                    if (q.thread != null)
380 >                        pred = q;
381 >                    else if (pred != null) {
382 >                        pred.next = s;
383 >                        if (pred.thread == null) // check for race
384 >                            continue retry;
385 >                    }
386 >                    else if (!UNSAFE.compareAndSwapObject(this, waitersOffset,
387 >                                                          q, s))
388 >                        continue retry;
389                  }
390 +                break;
391              }
392          }
393      }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines