< prev index next >

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

Print this page
*** 310,13 ***
      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.
      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
  
      /**
--- 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 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 ***
          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
           * @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
           * @see State#FAILED
           */
          Throwable exception();
      }
  
--- 367,22 ---
          State state();
  
          /**
           * Returns the result of the subtask.
           *
           * @return the possibly-null result
!          * @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}
           *
!          * @throws IllegalStateException if the subtask has not completed or completed
!          * with a result rather than an exception
           * @see State#FAILED
           */
          Throwable exception();
      }
  

*** 467,20 ***
          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.
       *
--- 456,10 ---

*** 574,11 ***
                  // new round if first fork after join
                  round++;
              }
          }
  
!         SubtaskImpl<U> subtask = new SubtaskImpl<>(this, task, round);
          if (s < SHUTDOWN) {
              // create thread to run task
              Thread thread = factory.newThread(subtask);
              if (thread == null) {
                  throw new RejectedExecutionException("Rejected by thread factory");
--- 553,11 ---
                  // new round if first fork after join
                  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 ***
              state = CLOSED;
          }
  
          // throw ISE if the owner didn't attempt to join after forking
          if (forkRound > lastJoinAttempted) {
!             lastJoinCompleted = forkRound;
              throw newIllegalStateExceptionNoJoin();
          }
      }
  
      @Override
--- 821,11 ---
              state = CLOSED;
          }
  
          // throw ISE if the owner didn't attempt to join after forking
          if (forkRound > lastJoinAttempted) {
!             lastJoinCompleted = forkRound;  // ensureOwnerAndJoined is a no-op after close
              throw newIllegalStateExceptionNoJoin();
          }
      }
  
      @Override

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

*** 926,11 ***
              }
          }
  
          @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")
--- 901,10 ---

*** 941,11 ***
                      "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(
--- 915,10 ---
< prev index next >