< prev index next > src/java.base/share/classes/java/util/concurrent/StructuredTaskScope.java
Print this page
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
/**
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();
}
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.
*
// 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");
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
}
}
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;
}
}
@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")
"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 >