< prev index next >

src/java.base/share/classes/java/lang/ScopedValue.java

Print this page

  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 {
< prev index next >