1 /*
2 * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved.
3 * Copyright (c) 2020, 2022, Red Hat Inc.
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 *
6 * This code is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 only, as
8 * published by the Free Software Foundation. Oracle designates this
9 * particular file as subject to the "Classpath" exception as provided
10 * by Oracle in the LICENSE file that accompanied this code.
11 *
12 * This code is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 * version 2 for more details (a copy is included in the LICENSE file that
16 * accompanied this code).
17 *
18 * You should have received a copy of the GNU General Public License version
19 * 2 along with this work; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21 *
22 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
140 * structured cases where child threads are started and terminate within the bounded
141 * period of execution by a parent thread. When using a {@link StructuredTaskScope},
142 * scoped value bindings are <em>captured</em> when creating a {@code StructuredTaskScope}
143 * and inherited by all threads started in that task scope with the
144 * {@link StructuredTaskScope#fork(java.util.concurrent.Callable) fork} method.
145 *
146 * <p> A {@code ScopedValue} that is shared across threads requires that the value be an
147 * immutable object or for all access to the value to be appropriately synchronized.
148 *
149 * <p> In the following example, the {@code ScopedValue} {@code NAME} is bound to the
150 * value "{@code duke}" for the execution of a runnable operation. The code in the {@code
151 * run} method creates a {@code StructuredTaskScope} that forks three tasks. Code executed
152 * directly or indirectly by these threads running {@code childTask1()}, {@code childTask2()},
153 * and {@code childTask3()} that invokes {@code NAME.get()} will read the value
154 * "{@code duke}".
155 *
156 * {@snippet lang=java :
157 * private static final ScopedValue<String> NAME = ScopedValue.newInstance();
158
159 * ScopedValue.where(NAME, "duke").run(() -> {
160 * try (var scope = new StructuredTaskScope<String>()) {
161 *
162 * // @link substring="fork" target="StructuredTaskScope#fork(java.util.concurrent.Callable)" :
163 * scope.fork(() -> childTask1());
164 * scope.fork(() -> childTask2());
165 * scope.fork(() -> childTask3());
166 *
167 * // @link substring="join" target="StructuredTaskScope#join()" :
168 * scope.join();
169 *
170 * ..
171 * }
172 * });
173 * }
174 *
175 * <p> Unless otherwise specified, passing a {@code null} argument to a method in this
176 * class will cause a {@link NullPointerException} to be thrown.
177 *
178 * @apiNote
179 * A {@code ScopedValue} should be preferred over a {@link ThreadLocal} for cases where
180 * the goal is "one-way transmission" of data without using method parameters. While a
594 }
595 }
596 var value = findBinding();
597 boolean result = (value != Snapshot.NIL);
598 if (result) Cache.put(this, value);
599 return result;
600 }
601
602 /**
603 * Return the value of the scoped value or NIL if not bound.
604 */
605 private Object findBinding() {
606 Object value = scopedValueBindings().find(this);
607 return value;
608 }
609
610 /**
611 * Returns the value of this scoped value if bound in the current thread, otherwise
612 * returns {@code other}.
613 *
614 * @param other the value to return if not bound, can be {@code null}
615 * @return the value of the scoped value if bound, otherwise {@code other}
616 */
617 public T orElse(T other) {
618 Object obj = findBinding();
619 if (obj != Snapshot.NIL) {
620 @SuppressWarnings("unchecked")
621 T value = (T) obj;
622 return value;
623 } else {
624 return other;
625 }
626 }
627
628 /**
629 * Returns the value of this scoped value if bound in the current thread, otherwise
630 * throws an exception produced by the exception supplying function.
631 *
632 * @param <X> the type of the exception that may be thrown
633 * @param exceptionSupplier the supplying function that produces the exception to throw
634 * @return the value of the scoped value if bound in the current thread
635 * @throws X if the scoped value is not bound in the current thread
636 */
637 public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
|
1 /*
2 * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved.
3 * Copyright (c) 2020, 2022, Red Hat Inc.
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 *
6 * This code is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 only, as
8 * published by the Free Software Foundation. Oracle designates this
9 * particular file as subject to the "Classpath" exception as provided
10 * by Oracle in the LICENSE file that accompanied this code.
11 *
12 * This code is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 * version 2 for more details (a copy is included in the LICENSE file that
16 * accompanied this code).
17 *
18 * You should have received a copy of the GNU General Public License version
19 * 2 along with this work; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21 *
22 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
140 * structured cases where child threads are started and terminate within the bounded
141 * period of execution by a parent thread. When using a {@link StructuredTaskScope},
142 * scoped value bindings are <em>captured</em> when creating a {@code StructuredTaskScope}
143 * and inherited by all threads started in that task scope with the
144 * {@link StructuredTaskScope#fork(java.util.concurrent.Callable) fork} method.
145 *
146 * <p> A {@code ScopedValue} that is shared across threads requires that the value be an
147 * immutable object or for all access to the value to be appropriately synchronized.
148 *
149 * <p> In the following example, the {@code ScopedValue} {@code NAME} is bound to the
150 * value "{@code duke}" for the execution of a runnable operation. The code in the {@code
151 * run} method creates a {@code StructuredTaskScope} that forks three tasks. Code executed
152 * directly or indirectly by these threads running {@code childTask1()}, {@code childTask2()},
153 * and {@code childTask3()} that invokes {@code NAME.get()} will read the value
154 * "{@code duke}".
155 *
156 * {@snippet lang=java :
157 * private static final ScopedValue<String> NAME = ScopedValue.newInstance();
158
159 * ScopedValue.where(NAME, "duke").run(() -> {
160 * // @link substring="open" target="StructuredTaskScope#open()" :
161 * try (var scope = StructuredTaskScope.open()) {
162 *
163 * // @link substring="fork" target="StructuredTaskScope#fork(java.util.concurrent.Callable)" :
164 * scope.fork(() -> childTask1());
165 * scope.fork(() -> childTask2());
166 * scope.fork(() -> childTask3());
167 *
168 * // @link substring="join" target="StructuredTaskScope#join()" :
169 * scope.join();
170 *
171 * ..
172 * }
173 * });
174 * }
175 *
176 * <p> Unless otherwise specified, passing a {@code null} argument to a method in this
177 * class will cause a {@link NullPointerException} to be thrown.
178 *
179 * @apiNote
180 * A {@code ScopedValue} should be preferred over a {@link ThreadLocal} for cases where
181 * the goal is "one-way transmission" of data without using method parameters. While a
595 }
596 }
597 var value = findBinding();
598 boolean result = (value != Snapshot.NIL);
599 if (result) Cache.put(this, value);
600 return result;
601 }
602
603 /**
604 * Return the value of the scoped value or NIL if not bound.
605 */
606 private Object findBinding() {
607 Object value = scopedValueBindings().find(this);
608 return value;
609 }
610
611 /**
612 * Returns the value of this scoped value if bound in the current thread, otherwise
613 * returns {@code other}.
614 *
615 * @param other the value to return if not bound
616 * @return the value of the scoped value if bound, otherwise {@code other}
617 */
618 public T orElse(T other) {
619 Objects.requireNonNull(other);
620 Object obj = findBinding();
621 if (obj != Snapshot.NIL) {
622 @SuppressWarnings("unchecked")
623 T value = (T) obj;
624 return value;
625 } else {
626 return other;
627 }
628 }
629
630 /**
631 * Returns the value of this scoped value if bound in the current thread, otherwise
632 * throws an exception produced by the exception supplying function.
633 *
634 * @param <X> the type of the exception that may be thrown
635 * @param exceptionSupplier the supplying function that produces the exception to throw
636 * @return the value of the scoped value if bound in the current thread
637 * @throws X if the scoped value is not bound in the current thread
638 */
639 public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
|