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

Comparing jsr166/src/main/java/util/concurrent/CompletableFuture.java (file contents):
Revision 1.184 by dl, Sat Apr 2 17:45:29 2016 UTC vs.
Revision 1.185 by dl, Sun Apr 3 14:42:04 2016 UTC

# Line 207 | Line 207 | public class CompletableFuture<T> implem
207       * pointing back to its sources. So we null out fields as soon as
208       * possible.  The screening checks needed anyway harmlessly ignore
209       * null arguments that may have been obtained during races with
210 <     * threads nulling out fields.  We also try to unlink fired
211 <     * Completions from stacks that might never be popped (see method
212 <     * postFire).  Completion fields need not be declared as final or
213 <     * volatile because they are only visible to other threads upon
214 <     * safe publication.
210 >     * threads nulling out fields.  We also try to unlink non-isLive
211 >     * (fired or cancelled) Completions from stacks that might
212 >     * otherwise never be popped: Method cleanStack always unlinks non
213 >     * isLive completions from the head of stack; others may
214 >     * occasionally remain if racing with other cancellations or
215 >     * removals.
216 >     *
217 >     * Completion fields need not be declared as final or volatile
218 >     * because they are only visible to other threads upon safe
219 >     * publication.
220       */
221  
222      volatile Object result;       // Either the result or boxed AltResult
# Line 448 | Line 453 | public class CompletableFuture<T> implem
453          U.putOrderedObject(c, NEXT, next);
454      }
455  
456 +    static boolean casNext(Completion c, Completion cmp, Completion val) {
457 +        return U.compareAndSwapObject(c, NEXT, cmp, val);
458 +    }
459 +
460      /**
461       * Pops and tries to trigger all reachable dependents.  Call only
462       * when known to be done.
# Line 468 | Line 477 | public class CompletableFuture<T> implem
477                          pushStack(h);
478                          continue;
479                      }
480 <                    h.next = null;    // detach
480 >                    casNext(h, t, null);    // try to detach
481                  }
482                  f = (d = h.tryFire(NESTED)) == null ? this : d;
483              }
484          }
485      }
486  
487 <    /** Traverses stack and unlinks dead Completions. */
487 >    /** Traverses stack and unlinks one or more dead Completions, if found. */
488      final void cleanStack() {
489 <        for (Completion p = null, q = stack; q != null;) {
490 <            Completion s = q.next;
491 <            if (q.isLive()) {
492 <                p = q;
493 <                q = s;
494 <            }
495 <            else if (p == null) {
496 <                casStack(q, s);
497 <                q = stack;
489 <            }
490 <            else {
491 <                p.next = s;
492 <                if (p.isLive())
489 >        boolean unlinked = false;
490 >        Completion p;
491 >        while ((p = stack) != null && !p.isLive()) // ensure head of stack live
492 >            unlinked = casStack(p, p.next);
493 >        if (p != null && !unlinked) {              // try to unlink first nonlive
494 >            for (Completion q = p.next; q != null;) {
495 >                Completion s = q.next;
496 >                if (q.isLive()) {
497 >                    p = q;
498                      q = s;
499 +                }
500                  else {
501 <                    p = null;  // restart
502 <                    q = stack;
501 >                    casNext(p, q, s);
502 >                    break;
503                  }
504              }
505          }
# Line 548 | Line 554 | public class CompletableFuture<T> implem
554       */
555      final CompletableFuture<T> postFire(CompletableFuture<?> a, int mode) {
556          if (a != null && a.stack != null) {
557 <            if (a.result == null)
557 >            Object r;
558 >            if ((r = a.result) == null)
559                  a.cleanStack();
560 <            else if (mode >= 0)
560 >            if (mode >= 0 && (r != null || a.result != null))
561                  a.postComplete();
562          }
563          if (result != null && stack != null) {
# Line 1126 | Line 1133 | public class CompletableFuture<T> implem
1133      final CompletableFuture<T> postFire(CompletableFuture<?> a,
1134                                          CompletableFuture<?> b, int mode) {
1135          if (b != null && b.stack != null) { // clean second source
1136 <            if (b.result == null)
1136 >            Object r;
1137 >            if ((r = b.result) == null)
1138                  b.cleanStack();
1139 <            else if (mode >= 0)
1139 >            if (mode >= 0 && (r != null || b.result != null))
1140                  b.postComplete();
1141          }
1142          return postFire(a, mode);
# Line 1851 | Line 1859 | public class CompletableFuture<T> implem
1859                      break;
1860              }
1861          }
1862 <        if (q != null) {
1862 >        if (q != null && queued) {
1863              q.thread = null;
1864 <            if (q.interrupted) {
1865 <                if (interruptible)
1866 <                    cleanStack();
1867 <                else
1860 <                    Thread.currentThread().interrupt();
1861 <            }
1864 >            if (!interruptible && q.interrupted)
1865 >                Thread.currentThread().interrupt();
1866 >            if (r == null)
1867 >                cleanStack();
1868          }
1869 <        if (r != null)
1869 >        if (r != null || (r = result) != null)
1870              postComplete();
1871          return r;
1872      }
# Line 1897 | Line 1903 | public class CompletableFuture<T> implem
1903                          break;
1904                  }
1905              }
1906 <            if (q != null)
1906 >            if (q != null && queued) {
1907                  q.thread = null;
1908 <            if (r != null)
1908 >                if (r == null)
1909 >                    cleanStack();
1910 >            }
1911 >            if (r != null || (r = result) != null)
1912                  postComplete();
1904            else
1905                cleanStack();
1913              if (r != null || (q != null && q.interrupted))
1914                  return r;
1915          }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines