< prev index next >

src/java.base/share/classes/java/util/concurrent/StructuredTaskScope.java

Print this page
@@ -310,13 +310,12 @@
      private static final int CLOSED   = 2;
  
      // state: set to SHUTDOWN by any thread, set to CLOSED by owner, read by any thread
      private volatile int state;
  
-     // Counters to support checking that the task scope owner joins before processing
-     // results and attempts join before closing the task scope. These counters are
-     // accessed only by the owner thread.
+     // Counters to support checking that the task scope owner joins before closing the task
+     // scope. These counters are accessed only by the owner thread.
      private int forkRound;         // incremented when the first subtask is forked after join
      private int lastJoinAttempted; // set to the current fork round when join is attempted
      private int lastJoinCompleted; // set to the current fork round when join completes
  
      /**

@@ -368,32 +367,22 @@
          State state();
  
          /**
           * Returns the result of the subtask.
           *
-          * <p> To ensure correct usage, if the scope owner {@linkplain #fork(Callable) forks}
-          * a subtask, then it must join (with {@link #join() join} or {@link #joinUntil(Instant)
-          * joinUntil}) before it can obtain the result of the subtask.
-          *
           * @return the possibly-null result
-          * @throws IllegalStateException if the subtask has not completed, did not complete
-          * successfully, or the current thread is the task scope owner and did not join
-          * after forking
+          * @throws IllegalStateException if the subtask has not completed or did not
+          * complete successfully
           * @see State#SUCCESS
           */
          T get();
  
          /**
           * {@return the exception thrown by the subtask}
           *
-          * <p> To ensure correct usage, if the scope owner {@linkplain #fork(Callable) forks}
-          * a subtask, then it must join (with {@link #join() join} or {@link #joinUntil(Instant)
-          * joinUntil}) before it can obtain the exception thrown by the subtask.
-          *
-          * @throws IllegalStateException if the subtask has not completed, completed with
-          * a result, or the current thread is the task scope owner and did not join after
-          * forking
+          * @throws IllegalStateException if the subtask has not completed or completed
+          * with a result rather than an exception
           * @see State#FAILED
           */
          Throwable exception();
      }
  

@@ -467,20 +456,10 @@
          Thread currentThread = Thread.currentThread();
          if (currentThread != flock.owner() && !flock.containsThread(currentThread))
              throw new WrongThreadException("Current thread not owner or thread in the tree");
      }
  
-     /**
-      * Throws IllegalStateException if the current thread is the owner, and the owner did
-      * not join after forking a subtask in the given fork round.
-      */
-     private void ensureJoinedIfOwner(int round) {
-         if (Thread.currentThread() == flock.owner() && (round > lastJoinCompleted)) {
-             throw newIllegalStateExceptionNoJoin();
-         }
-     }
- 
      /**
       * Ensures that the current thread is the owner of this task scope and that it joined
       * (with {@link #join()} or {@link #joinUntil(Instant)}) after {@linkplain #fork(Callable)
       * forking} subtasks.
       *

@@ -574,11 +553,11 @@
                  // new round if first fork after join
                  round++;
              }
          }
  
-         SubtaskImpl<U> subtask = new SubtaskImpl<>(this, task, round);
+         var subtask = new SubtaskImpl<U>(this, task);
          if (s < SHUTDOWN) {
              // create thread to run task
              Thread thread = factory.newThread(subtask);
              if (thread == null) {
                  throw new RejectedExecutionException("Rejected by thread factory");

@@ -842,11 +821,11 @@
              state = CLOSED;
          }
  
          // throw ISE if the owner didn't attempt to join after forking
          if (forkRound > lastJoinAttempted) {
-             lastJoinCompleted = forkRound;
+             lastJoinCompleted = forkRound;  // ensureOwnerAndJoined is a no-op after close
              throw newIllegalStateExceptionNoJoin();
          }
      }
  
      @Override

@@ -872,19 +851,15 @@
              }
          }
  
          private final StructuredTaskScope<? super T> scope;
          private final Callable<? extends T> task;
-         private final int round;
          private volatile Object result;
  
-         SubtaskImpl(StructuredTaskScope<? super T> scope,
-                     Callable<? extends T> task,
-                     int round) {
+         SubtaskImpl(StructuredTaskScope<? super T> scope, Callable<? extends T> task) {
              this.scope = scope;
              this.task = task;
-             this.round = round;
          }
  
          @Override
          public void run() {
              T result = null;

@@ -926,11 +901,10 @@
              }
          }
  
          @Override
          public T get() {
-             scope.ensureJoinedIfOwner(round);
              Object result = this.result;
              if (result instanceof AltResult) {
                  if (result == RESULT_NULL) return null;
              } else if (result != null) {
                  @SuppressWarnings("unchecked")

@@ -941,11 +915,10 @@
                      "Result is unavailable or subtask did not complete successfully");
          }
  
          @Override
          public Throwable exception() {
-             scope.ensureJoinedIfOwner(round);
              Object result = this.result;
              if (result instanceof AltResult alt && alt.state() == State.FAILED) {
                  return alt.exception();
              }
              throw new IllegalStateException(
< prev index next >