/
githubmirror
/
riscv-port
Обзор
Документация
Войти
/
githubmirror
/
riscv-port
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/java.base/share/classes/java/util/concurrent/Joiners.java
276 строк
9 KB
Alan Bateman
8380109: Implement JEP 533: Structured Concurrency (Seventh Preview)
06 май 2026, 13:18
06 май 2026, 13:18
4f3edc3
Код
Авторство
О чём код?
/* * Copyright (c) 2024, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package java.util.concurrent; import java.lang.invoke.MethodHandles; import java.lang.invoke.VarHandle; import java.util.ArrayList; import java.util.Comparator; import java.util.List; import java.util.NoSuchElementException; import java.util.Objects; import java.util.concurrent.StructuredTaskScope.Joiner; import java.util.concurrent.StructuredTaskScope.Subtask; import java.util.concurrent.StructuredTaskScope.CancelledByTimeoutException; import java.util.function.Function; import java.util.function.Predicate; import jdk.internal.invoke.MhUtil; /** * Built-in StructuredTaskScope.Joiner implementations. */ class Joiners { private Joiners() { } /** * Throws IllegalArgumentException if the subtask is not in the UNAVAILABLE state. */ private static void ensureUnavailable(Subtask<?> subtask) { if (subtask.state() != Subtask.State.UNAVAILABLE) { throw new IllegalArgumentException("Subtask not in UNAVAILABLE state"); } } /** * Throws IllegalArgumentException if the subtask has not completed. */ private static Subtask.State ensureCompleted(Subtask<?> subtask) { Subtask.State state = subtask.state(); if (state == Subtask.State.UNAVAILABLE) { throw new IllegalArgumentException("Subtask has not completed"); } return state; } /** * A joiner that returns a list of all results when all subtasks complete * successfully. Cancels the scope if any subtask fails. */ static final class AllSuccessful<T, R_X extends Throwable> implements Joiner<T, List<T>, R_X> { private static final VarHandle FIRST_EXCEPTION = MhUtil.findVarHandle(MethodHandles.lookup(), "firstException", Throwable.class); private final Function<Throwable, R_X> esf; // list of forked subtasks, created lazily, only accessed by owner thread private List<Subtask<T>> subtasks; private volatile Throwable firstException; AllSuccessful(Function<Throwable, R_X> esf) { this.esf = Objects.requireNonNull(esf); } @Override public boolean onFork(Subtask<T> subtask) { ensureUnavailable(subtask); if (subtasks == null) { subtasks = new ArrayList<>(); } subtasks.add(subtask); return false; } @Override public boolean onComplete(Subtask<T> subtask) { Subtask.State state = ensureCompleted(subtask); return (state == Subtask.State.FAILED) && (firstException == null) && FIRST_EXCEPTION.compareAndSet(this, null, subtask.exception()); } @Override public List<T> result() throws R_X { Throwable ex = firstException; try { if (ex != null) { throw esf.apply(ex); } return (subtasks != null) ? subtasks.stream().map(Subtask::get).toList() : List.of(); } finally { subtasks = null; // allow subtasks to be GC'ed } } @Override public List<T> timeout() throws R_X { try { throw esf.apply(new CancelledByTimeoutException()); } finally { subtasks = null; // allow subtasks to be GC'ed } } } /** * A joiner that returns the result of the first subtask to complete successfully. * Cancels the scope if any subtasks succeeds. */ static final class AnySuccessful<T, R_X extends Throwable> implements Joiner<T, T, R_X> { private static final VarHandle SUBTASK = MhUtil.findVarHandle(MethodHandles.lookup(), "subtask", Subtask.class); private final Function<Throwable, R_X> esf; // UNAVAILABLE < FAILED < SUCCESS private static final Comparator<Subtask.State> SUBTASK_STATE_COMPARATOR = Comparator.comparingInt(AnySuccessful::stateToInt); private volatile Subtask<T> subtask; AnySuccessful(Function<Throwable, R_X> esf) { this.esf = Objects.requireNonNull(esf); } /** * Maps a Subtask.State to an int that can be compared. */ private static int stateToInt(Subtask.State s) { return switch (s) { case UNAVAILABLE -> 0; case FAILED -> 1; case SUCCESS -> 2; }; } @Override public boolean onComplete(Subtask<T> subtask) { Subtask.State state = ensureCompleted(subtask); Subtask<T> s; while (((s = this.subtask) == null) || SUBTASK_STATE_COMPARATOR.compare(s.state(), state) < 0) { if (SUBTASK.compareAndSet(this, s, subtask)) { return (state == Subtask.State.SUCCESS); } } return false; } @Override public T result() throws R_X { Subtask<T> subtask = this.subtask; if (subtask == null) { throw esf.apply(new NoSuchElementException("No subtasks completed")); } return switch (subtask.state()) { case SUCCESS -> subtask.get(); case FAILED -> throw esf.apply(subtask.exception()); default -> throw new InternalError(); }; } @Override public T timeout() throws R_X { throw esf.apply(new CancelledByTimeoutException()); } } /** * A joiner that that waits for all successful subtasks. Cancels the scope if any * subtask fails. */ static final class AwaitSuccessful<T, R_X extends Throwable> implements Joiner<T, Void, R_X> { private static final VarHandle FIRST_EXCEPTION = MhUtil.findVarHandle(MethodHandles.lookup(), "firstException", Throwable.class); private final Function<Throwable, R_X> esf; private volatile Throwable firstException; AwaitSuccessful(Function<Throwable, R_X> esf) { this.esf = Objects.requireNonNull(esf); } @Override public boolean onComplete(Subtask<T> subtask) { Subtask.State state = ensureCompleted(subtask); return (state == Subtask.State.FAILED) && (firstException == null) && FIRST_EXCEPTION.compareAndSet(this, null, subtask.exception()); } @Override public Void result() throws R_X { Throwable ex = firstException; if (ex != null) { throw esf.apply(ex); } else { return null; } } @Override public Void timeout() throws R_X { throw esf.apply(new CancelledByTimeoutException()); } } /** * A joiner that returns a list of all subtasks. */ static final class AllSubtasks<T> implements Joiner<T, List<Subtask<T>>, RuntimeException> { private final Predicate<? super Subtask<T>> isDone; // list of forked subtasks, created lazily, only accessed by owner thread private List<Subtask<T>> subtasks; AllSubtasks(Predicate<? super Subtask<T>> isDone) { this.isDone = Objects.requireNonNull(isDone); } @Override public boolean onFork(Subtask<T> subtask) { ensureUnavailable(subtask); if (subtasks == null) { subtasks = new ArrayList<>(); } subtasks.add(subtask); return false; } @Override public boolean onComplete(Subtask<T> subtask) { ensureCompleted(subtask); return isDone.test(subtask); } @Override public List<Subtask<T>> result() { if (subtasks != null) { List<Subtask<T>> result = List.copyOf(subtasks); subtasks = null; // allow subtasks to be GC'ed return result; } else { return List.of(); } } @Override public List<Subtask<T>> timeout() { return result(); } } }