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
 23  * or visit www.oracle.com if you need additional information or have any
 24  * questions.
 25  */
 26 
 27 package java.lang;
 28 
 29 import java.util.NoSuchElementException;
 30 import java.util.Objects;
 31 import java.lang.ref.Reference;
 32 import java.util.concurrent.StructuredTaskScope;
 33 import java.util.concurrent.StructureViolationException;
 34 import java.util.function.Supplier;
 35 import jdk.internal.access.JavaUtilConcurrentTLRAccess;
 36 import jdk.internal.access.SharedSecrets;
 37 import jdk.internal.javac.PreviewFeature;
 38 import jdk.internal.vm.annotation.ForceInline;
 39 import jdk.internal.vm.annotation.Hidden;
 40 import jdk.internal.vm.ScopedValueContainer;
 41 import sun.security.action.GetPropertyAction;
 42 
 43 /**
 44  * A value that may be safely and efficiently shared to methods without using method
 45  * parameters.
 46  *
 47  * <p> In the Java programming language, data is usually passed to a method by means of a
 48  * method parameter. The data may need to be passed through a sequence of many methods to
 49  * get to the method that makes use of the data. Every method in the sequence of calls
 50  * needs to declare the parameter and every method has access to the data.
 51  * {@code ScopedValue} provides a means to pass data to a faraway method (typically a
 52  * <em>callback</em>) without using method parameters. In effect, a {@code ScopedValue}
 53  * is an <em>implicit method parameter</em>. It is "as if" every method in a sequence of
 54  * calls has an additional parameter. None of the methods declare the parameter and only
 55  * the methods that have access to the {@code ScopedValue} object can access its value
 56  * (the data). {@code ScopedValue} makes it possible to securely pass data from a
 57  * <em>caller</em> to a faraway <em>callee</em> through a sequence of intermediate methods
 58  * that do not declare a parameter for the data and have no access to the data.
 59  *
 60  * <p> The {@code ScopedValue} API works by executing a method with a {@code ScopedValue}
 61  * object <em>bound</em> to some value for the bounded period of execution of a method.
 62  * The method may invoke another method, which in turn may invoke another. The unfolding
 63  * execution of the methods define a <em>dynamic scope</em>. Code in these methods with
 64  * access to the {@code ScopedValue} object may read its value. The {@code ScopedValue}
 65  * object reverts to being <em>unbound</em> when the original method completes normally or
 66  * with an exception. The {@code ScopedValue} API supports executing a {@link Runnable},
 67  * or {@link CallableOp} with a {@code ScopedValue} bound to a value.
 68  *
 69  * <p> Consider the following example with a scoped value "{@code NAME}" bound to the value
 70  * "{@code duke}" for the execution of a {@code Runnable}'s {@code run} method.
 71  * The {@code run} method, in turn, invokes a method {@code doSomething}.
 72  *
 73  *
 74  * {@snippet lang=java :
 75  *     // @link substring="newInstance" target="#newInstance" :
 76  *     private static final ScopedValue<String> NAME = ScopedValue.newInstance();
 77  *
 78  *     // @link substring="runWhere" target="#runWhere(ScopedValue, Object, Runnable)" :
 79  *     ScopedValue.runWhere(NAME, "duke", () -> doSomething());
 80  * }
 81  * Code executed directly or indirectly by {@code doSomething}, with access to the field
 82  * {@code NAME}, can invoke {@code NAME.get()} to read the value "{@code duke}". {@code
 83  * NAME} is bound while executing the {@code run} method. It reverts to being unbound when
 84  * the {@code run} method completes.
 85  *
 86  * <p> The example using {@code runWhere} invokes a method that does not return a result.
 87  * The {@link #callWhere(ScopedValue, Object, CallableOp) callWhere} method can be used
 88  * to invoke a method that returns a result.
 89  * In addition, {@code ScopedValue} defines the {@link #where(ScopedValue, Object)} method
 90  * for cases where multiple mappings (of {@code ScopedValue} to value) are accumulated
 91  * in advance of calling a method with all {@code ScopedValue}s bound to their value.
 92  *
 93  * <h2>Bindings are per-thread</h2>
 94  *
 95  * A {@code ScopedValue} binding to a value is per-thread. Invoking {@code xxxWhere}
 96  * executes a method with a {@code ScopedValue} bound to a value for the current thread.
 97  * The {@link #get() get} method returns the value bound for the current thread.
 98  *
 99  * <p> In the example, if code executed by one thread invokes this:
100  * {@snippet lang=java :
101  *     ScopedValue.runWhere(NAME, "duke1", () -> doSomething());
102  * }
103  * and code executed by another thread invokes:
104  * {@snippet lang=java :
105  *     ScopedValue.runWhere(NAME, "duke2", () -> doSomething());
106  * }
107  * then code in {@code doSomething} (or any method that it calls) invoking {@code NAME.get()}
108  * will read the value "{@code duke1}" or "{@code duke2}", depending on which thread is
109  * executing.
110  *
111  * <h2>Scoped values as capabilities</h2>
112  *
113  * A {@code ScopedValue} object should be treated as a <em>capability</em> or a key to
114  * access its value when the {@code ScopedValue} is bound. Secure usage depends on access
115  * control (see <cite>The Java Virtual Machine Specification</cite>, Section {@jvms 5.4.4})
116  * and taking care to not share the {@code ScopedValue} object. In many cases, a {@code
117  * ScopedValue} will be declared in a {@code final} and {@code static} field so that it
118  * is only accessible to code in a single class (or nest).
119  *
120  * <h2><a id="rebind">Rebinding</a></h2>
121  *
122  * The {@code ScopedValue} API allows a new binding to be established for <em>nested
123  * dynamic scopes</em>. This is known as <em>rebinding</em>. A {@code ScopedValue} that
124  * is bound to a value may be bound to a new value for the bounded execution of a new
125  * method. The unfolding execution of code executed by that method defines the nested
126  * dynamic scope. When the method completes, the value of the {@code ScopedValue} reverts
127  * to its previous value.
128  *
129  * <p> In the above example, suppose that code executed by {@code doSomething} binds
130  * {@code NAME} to a new value with:
131  * {@snippet lang=java :
132  *     ScopedValue.runWhere(NAME, "duchess", () -> doMore());
133  * }
134  * Code executed directly or indirectly by {@code doMore()} that invokes {@code
135  * NAME.get()} will read the value "{@code duchess}". When {@code doMore()} completes
136  * then the value of {@code NAME} reverts to "{@code duke}".
137  *
138  * <h2><a id="inheritance">Inheritance</a></h2>
139  *
140  * {@code ScopedValue} supports sharing across threads. This sharing is limited to
141  * structured cases where child threads are started and terminate within the bounded
142  * period of execution by a parent thread. When using a {@link StructuredTaskScope},
143  * scoped value bindings are <em>captured</em> when creating a {@code StructuredTaskScope}
144  * and inherited by all threads started in that task scope with the
145  * {@link StructuredTaskScope#fork(java.util.concurrent.Callable) fork} method.
146  *
147  * <p> A {@code ScopedValue} that is shared across threads requires that the value be an
148  * immutable object or for all access to the value to be appropriately synchronized.
149  *
150  * <p> In the following example, the {@code ScopedValue} {@code NAME} is bound to the
151  * value "{@code duke}" for the execution of a runnable operation. The code in the {@code
152  * run} method creates a {@code StructuredTaskScope} that forks three tasks. Code executed
153  * directly or indirectly by these threads running {@code childTask1()}, {@code childTask2()},
154  * and {@code childTask3()} that invokes {@code NAME.get()} will read the value
155  * "{@code duke}".
156  *
157  * {@snippet lang=java :
158  *     private static final ScopedValue<String> NAME = ScopedValue.newInstance();
159 
160  *     ScopedValue.runWhere(NAME, "duke", () -> {
161  *         try (var scope = new StructuredTaskScope<String>()) {

162  *
163  *             scope.fork(() -> childTask1());
164  *             scope.fork(() -> childTask2());
165  *             scope.fork(() -> childTask3());

166  *
167  *             ...



168  *          }
169  *     });
170  * }
171  *
172  * <p> Unless otherwise specified, passing a {@code null} argument to a method in this
173  * class will cause a {@link NullPointerException} to be thrown.
174  *
175  * @apiNote
176  * A {@code ScopedValue} should be preferred over a {@link ThreadLocal} for cases where
177  * the goal is "one-way transmission" of data without using method parameters.  While a
178  * {@code ThreadLocal} can be used to pass data to a method without using method parameters,
179  * it does suffer from a number of issues:
180  * <ol>
181  *   <li> {@code ThreadLocal} does not prevent code in a faraway callee from {@linkplain
182  *   ThreadLocal#set(Object) setting} a new value.
183  *   <li> A {@code ThreadLocal} has an unbounded lifetime and thus continues to have a value
184  *   after a method completes, unless explicitly {@linkplain ThreadLocal#remove() removed}.
185  *   <li> {@linkplain InheritableThreadLocal Inheritance} is expensive - the map of
186  *   thread-locals to values must be copied when creating each child thread.
187  * </ol>
188  *
189  * @implNote
190  * Scoped values are designed to be used in fairly small
191  * numbers. {@link #get} initially performs a search through enclosing
192  * scopes to find a scoped value's innermost binding. It
193  * then caches the result of the search in a small thread-local
194  * cache. Subsequent invocations of {@link #get} for that scoped value
195  * will almost always be very fast. However, if a program has many
196  * scoped values that it uses cyclically, the cache hit rate
197  * will be low and performance will be poor. This design allows
198  * scoped-value inheritance by {@link StructuredTaskScope} threads to
199  * be very fast: in essence, no more than copying a pointer, and
200  * leaving a scoped-value binding also requires little more than
201  * updating a pointer.
202  *
203  * <p>Because the scoped-value per-thread cache is small, clients
204  * should minimize the number of bound scoped values in use. For
205  * example, if it is necessary to pass a number of values in this way,
206  * it makes sense to create a record class to hold those values, and
207  * then bind a single {@code ScopedValue} to an instance of that record.
208  *
209  * <p>For this release, the reference implementation
210  * provides some system properties to tune the performance of scoped
211  * values.
212  *
213  * <p>The system property {@code java.lang.ScopedValue.cacheSize}
214  * controls the size of the (per-thread) scoped-value cache. This cache is crucial
215  * for the performance of scoped values. If it is too small,
216  * the runtime library will repeatedly need to scan for each
217  * {@link #get}. If it is too large, memory will be unnecessarily
218  * consumed. The default scoped-value cache size is 16 entries. It may
219  * be varied from 2 to 16 entries in size. {@code ScopedValue.cacheSize}
220  * must be an integer power of 2.
221  *
222  * <p>For example, you could use {@code -Djava.lang.ScopedValue.cacheSize=8}.
223  *
224  * <p>The other system property is {@code jdk.preserveScopedValueCache}.
225  * This property determines whether the per-thread scoped-value
226  * cache is preserved when a virtual thread is blocked. By default
227  * this property is set to {@code true}, meaning that every virtual
228  * thread preserves its scoped-value cache when blocked. Like {@code
229  * ScopedValue.cacheSize}, this is a space versus speed trade-off: in
230  * situations where many virtual threads are blocked most of the time,
231  * setting this property to {@code false} might result in a useful
232  * memory saving, but each virtual thread's scoped-value cache would
233  * have to be regenerated after a blocking operation.
234  *
235  * @param <T> the type of the value
236  * @since 21
237  */
238 @PreviewFeature(feature = PreviewFeature.Feature.SCOPED_VALUES)
239 public final class ScopedValue<T> {
240     private final int hash;
241 
242     @Override
243     public int hashCode() { return hash; }
244 
245     /**
246      * An immutable map from {@code ScopedValue} to values.
247      *
248      * <p> Unless otherwise specified, passing a {@code null} argument to a constructor
249      * or method in this class will cause a {@link NullPointerException} to be thrown.
250      */
251     static final class Snapshot {
252         final Snapshot prev;
253         final Carrier bindings;
254         final int bitmask;
255 
256         private static final Object NIL = new Object();
257 
258         static final Snapshot EMPTY_SNAPSHOT = new Snapshot();
259 
260         Snapshot(Carrier bindings, Snapshot prev) {
261             this.prev = prev;
262             this.bindings = bindings;
263             this.bitmask = bindings.bitmask | prev.bitmask;
264         }
265 
266         protected Snapshot() {
267             this.prev = null;
268             this.bindings = null;
269             this.bitmask = 0;
270         }
271 
272         Object find(ScopedValue<?> key) {
273             int bits = key.bitmask();
274             for (Snapshot snapshot = this;
275                  containsAll(snapshot.bitmask, bits);
276                  snapshot = snapshot.prev) {
277                 for (Carrier carrier = snapshot.bindings;
278                      carrier != null && containsAll(carrier.bitmask, bits);
279                      carrier = carrier.prev) {
280                     if (carrier.getKey() == key) {
281                         Object value = carrier.get();
282                         return value;
283                     }
284                 }
285             }
286             return NIL;
287         }
288     }
289 
290     /**
291      * A mapping of scoped values, as <em>keys</em>, to values.
292      *
293      * <p> A {@code Carrier} is used to accumulate mappings so that an operation (a {@link
294      * Runnable} or {@link CallableOp}) can be executed with all scoped values in the
295      * mapping bound to values. The following example runs an operation with {@code k1}
296      * bound (or rebound) to {@code v1}, and {@code k2} bound (or rebound) to {@code v2}.
297      * {@snippet lang=java :
298      *     // @link substring="where" target="#where(ScopedValue, Object)" :
299      *     ScopedValue.where(k1, v1).where(k2, v2).run(() -> ... );
300      * }
301      *
302      * <p> A {@code Carrier} is immutable and thread-safe. The {@link
303      * #where(ScopedValue, Object) where} method returns a new {@code Carrier} object,
304      * it does not mutate an existing mapping.
305      *
306      * <p> Unless otherwise specified, passing a {@code null} argument to a method in
307      * this class will cause a {@link NullPointerException} to be thrown.
308      *
309      * @since 21
310      */
311     @PreviewFeature(feature = PreviewFeature.Feature.SCOPED_VALUES)
312     public static final class Carrier {
313         // Bit masks: a 1 in postion n indicates that this set of bound values
314         // hits that slot in the cache.
315         final int bitmask;
316         final ScopedValue<?> key;
317         final Object value;
318         final Carrier prev;
319 
320         Carrier(ScopedValue<?> key, Object value, Carrier prev) {
321             this.key = key;
322             this.value = value;
323             this.prev = prev;
324             int bits = key.bitmask();
325             if (prev != null) {
326                 bits |= prev.bitmask;
327             }
328             this.bitmask = bits;
329         }
330 
331         /**
332          * Add a binding to this map, returning a new Carrier instance.
333          */
334         private static <T> Carrier where(ScopedValue<T> key, T value, Carrier prev) {
335             return new Carrier(key, value, prev);
336         }
337 
338         /**
339          * Returns a new {@code Carrier} with the mappings from this carrier plus a
340          * new mapping from {@code key} to {@code value}. If this carrier already has a
341          * mapping for the scoped value {@code key} then it will map to the new
342          * {@code value}. The current carrier is immutable, so it is not changed by this
343          * method.
344          *
345          * @param key the {@code ScopedValue} key
346          * @param value the value, can be {@code null}
347          * @param <T> the type of the value
348          * @return a new {@code Carrier} with the mappings from this carrier plus the new mapping
349          */
350         public <T> Carrier where(ScopedValue<T> key, T value) {
351             return where(key, value, this);
352         }
353 
354         /*
355          * Return a new set consisting of a single binding.
356          */
357         static <T> Carrier of(ScopedValue<T> key, T value) {
358             return where(key, value, null);
359         }
360 
361         Object get() {
362             return value;
363         }
364 
365         ScopedValue<?> getKey() {
366             return key;
367         }
368 
369         /**
370          * Returns the value of a {@link ScopedValue} in this mapping.
371          *
372          * @param key the {@code ScopedValue} key
373          * @param <T> the type of the value
374          * @return the value
375          * @throws NoSuchElementException if the key is not present in this mapping
376          */
377         @SuppressWarnings("unchecked")
378         public <T> T get(ScopedValue<T> key) {
379             var bits = key.bitmask();
380             for (Carrier carrier = this;
381                  carrier != null && containsAll(carrier.bitmask, bits);
382                  carrier = carrier.prev) {
383                 if (carrier.getKey() == key) {
384                     Object value = carrier.get();
385                     return (T) value;
386                 }
387             }
388             throw new NoSuchElementException();
389         }
390 
391         /**
392          * Calls a value-returning operation with each scoped value in this mapping bound
393          * to its value in the current thread.
394          * When the operation completes (normally or with an exception), each scoped value
395          * in the mapping will revert to being unbound, or revert to its previous value
396          * when previously bound, in the current thread. If {@code op} completes with an
397          * exception then it propagated by this method.
398          *
399          * <p> Scoped values are intended to be used in a <em>structured manner</em>. If code
400          * invoked directly or indirectly by the operation creates a {@link StructuredTaskScope}
401          * but does not {@linkplain StructuredTaskScope#close() close} it, then it is detected
402          * as a <em>structure violation</em> when the operation completes (normally or with an
403          * exception). In that case, the underlying construct of the {@code StructuredTaskScope}
404          * is closed and {@link StructureViolationException} is thrown.
405          *
406          * @param op the operation to run
407          * @param <R> the type of the result of the operation
408          * @param <X> type of the exception thrown by the operation
409          * @return the result
410          * @throws StructureViolationException if a structure violation is detected
411          * @throws X if {@code op} completes with an exception
412          * @see ScopedValue#callWhere(ScopedValue, Object, CallableOp)
413          * @since 23
414          */
415         public <R, X extends Throwable> R call(CallableOp<? extends R, X> op) throws X {
416             Objects.requireNonNull(op);
417             Cache.invalidate(bitmask);
418             var prevSnapshot = scopedValueBindings();
419             var newSnapshot = new Snapshot(this, prevSnapshot);
420             return runWith(newSnapshot, op);
421         }
422 
423         /**
424          * Execute the action with a set of ScopedValue bindings.
425          *
426          * The VM recognizes this method as special, so any changes to the
427          * name or signature require corresponding changes in
428          * JVM_FindScopedValueBindings().
429          */
430         @Hidden
431         @ForceInline
432         private <R, X extends Throwable> R runWith(Snapshot newSnapshot, CallableOp<R, X> op) {
433             try {
434                 Thread.setScopedValueBindings(newSnapshot);
435                 Thread.ensureMaterializedForStackWalk(newSnapshot);
436                 return ScopedValueContainer.call(op);
437             } finally {
438                 Reference.reachabilityFence(newSnapshot);
439                 Thread.setScopedValueBindings(newSnapshot.prev);
440                 Cache.invalidate(bitmask);
441             }
442         }
443 
444         /**
445          * Runs an operation with each scoped value in this mapping bound to its value
446          * in the current thread.
447          * When the operation completes (normally or with an exception), each scoped value
448          * in the mapping will revert to being unbound, or revert to its previous value
449          * when previously bound, in the current thread. If {@code op} completes with an
450          * exception then it propagated by this method.
451          *
452          * <p> Scoped values are intended to be used in a <em>structured manner</em>. If code
453          * invoked directly or indirectly by the operation creates a {@link StructuredTaskScope}
454          * but does not {@linkplain StructuredTaskScope#close() close} it, then it is detected
455          * as a <em>structure violation</em> when the operation completes (normally or with an
456          * exception). In that case, the underlying construct of the {@code StructuredTaskScope}
457          * is closed and {@link StructureViolationException} is thrown.
458          *
459          * @param op the operation to run
460          * @throws StructureViolationException if a structure violation is detected
461          * @see ScopedValue#runWhere(ScopedValue, Object, Runnable)
462          */
463         public void run(Runnable op) {
464             Objects.requireNonNull(op);
465             Cache.invalidate(bitmask);
466             var prevSnapshot = scopedValueBindings();
467             var newSnapshot = new Snapshot(this, prevSnapshot);
468             runWith(newSnapshot, op);
469         }
470 
471         /**
472          * Execute the action with a set of {@code ScopedValue} bindings.
473          *
474          * The VM recognizes this method as special, so any changes to the
475          * name or signature require corresponding changes in
476          * JVM_FindScopedValueBindings().
477          */
478         @Hidden
479         @ForceInline
480         private void runWith(Snapshot newSnapshot, Runnable op) {
481             try {
482                 Thread.setScopedValueBindings(newSnapshot);
483                 Thread.ensureMaterializedForStackWalk(newSnapshot);
484                 ScopedValueContainer.run(op);
485             } finally {
486                 Reference.reachabilityFence(newSnapshot);
487                 Thread.setScopedValueBindings(newSnapshot.prev);
488                 Cache.invalidate(bitmask);
489             }
490         }
491     }
492 
493     /**
494      * An operation that returns a result and may throw an exception.
495      *
496      * @param <T> result type of the operation
497      * @param <X> type of the exception thrown by the operation
498      * @since 23
499      */
500     @PreviewFeature(feature = PreviewFeature.Feature.SCOPED_VALUES)
501     @FunctionalInterface
502     public interface CallableOp<T, X extends Throwable> {
503         /**
504          * Executes this operation.
505          * @return the result, can be null
506          * @throws X if the operation completes with an exception
507          */
508         T call() throws X;
509     }
510 
511     /**
512      * Creates a new {@code Carrier} with a single mapping of a {@code ScopedValue}
513      * <em>key</em> to a value. The {@code Carrier} can be used to accumulate mappings so
514      * that an operation can be executed with all scoped values in the mapping bound to
515      * values. The following example runs an operation with {@code k1} bound (or rebound)
516      * to {@code v1}, and {@code k2} bound (or rebound) to {@code v2}.
517      * {@snippet lang=java :
518      *     // @link substring="run" target="Carrier#run(Runnable)" :
519      *     ScopedValue.where(k1, v1).where(k2, v2).run(() -> ... );
520      * }
521      *
522      * @param key the {@code ScopedValue} key
523      * @param value the value, can be {@code null}
524      * @param <T> the type of the value
525      * @return a new {@code Carrier} with a single mapping
526      */
527     public static <T> Carrier where(ScopedValue<T> key, T value) {
528         return Carrier.of(key, value);
529     }
530 
531     /**
532      * Calls a value-returning operation with a {@code ScopedValue} bound to a value
533      * in the current thread. When the operation completes (normally or with an
534      * exception), the {@code ScopedValue} will revert to being unbound, or revert to
535      * its previous value when previously bound, in the current thread. If {@code op}
536      * completes with an exception then it propagated by this method.
537      *
538      * <p> Scoped values are intended to be used in a <em>structured manner</em>. If code
539      * invoked directly or indirectly by the operation creates a {@link StructuredTaskScope}
540      * but does not {@linkplain StructuredTaskScope#close() close} it, then it is detected
541      * as a <em>structure violation</em> when the operation completes (normally or with an
542      * exception). In that case, the underlying construct of the {@code StructuredTaskScope}
543      * is closed and {@link StructureViolationException} is thrown.
544      *
545      * @implNote
546      * This method is implemented to be equivalent to:
547      * {@snippet lang=java :
548      *     // @link substring="call" target="Carrier#call(CallableOp)" :
549      *     ScopedValue.where(key, value).call(op);
550      * }
551      *
552      *
553      *
554      * @param key the {@code ScopedValue} key
555      * @param value the value, can be {@code null}
556      * @param <T> the type of the value
557      * @param <R> the result type
558      * @param <X> type of the exception thrown by the operation
559      * @param op the operation to call
560      * @return the result
561      * @throws StructureViolationException if a structure violation is detected
562      * @throws X if the operation completes with an exception
563      * @since 23
564      */
565     public static <T, R, X extends Throwable> R callWhere(ScopedValue<T> key,
566                                                           T value,
567                                                           CallableOp<? extends R, X> op) throws X {
568         return where(key, value).call(op);
569     }
570 
571     /**
572      * Run an operation with a {@code ScopedValue} bound to a value in the current
573      * thread. When the operation completes (normally or with an exception), the
574      * {@code ScopedValue} will revert to being unbound, or revert to its previous value
575      * when previously bound, in the current thread. If {@code op} completes with an
576      * exception then it propagated by this method.
577      *
578      * <p> Scoped values are intended to be used in a <em>structured manner</em>. If code
579      * invoked directly or indirectly by the operation creates a {@link StructuredTaskScope}
580      * but does not {@linkplain StructuredTaskScope#close() close} it, then it is detected
581      * as a <em>structure violation</em> when the operation completes (normally or with an
582      * exception). In that case, the underlying construct of the {@code StructuredTaskScope}
583      * is closed and {@link StructureViolationException} is thrown.
584      *
585      * @implNote
586      * This method is implemented to be equivalent to:
587      * {@snippet lang=java :
588      *     // @link substring="run" target="Carrier#run(Runnable)" :
589      *     ScopedValue.where(key, value).run(op);
590      * }
591      *
592      * @param key the {@code ScopedValue} key
593      * @param value the value, can be {@code null}
594      * @param <T> the type of the value
595      * @param op the operation to call
596      * @throws StructureViolationException if a structure violation is detected
597      */
598     public static <T> void runWhere(ScopedValue<T> key, T value, Runnable op) {
599         where(key, value).run(op);
600     }
601 
602     private ScopedValue() {
603         this.hash = generateKey();
604     }
605 
606     /**
607      * Creates a scoped value that is initially unbound for all threads.
608      *
609      * @param <T> the type of the value
610      * @return a new {@code ScopedValue}
611      */
612     public static <T> ScopedValue<T> newInstance() {
613         return new ScopedValue<T>();
614     }
615 
616     /**
617      * {@return the value of the scoped value if bound in the current thread}
618      *
619      * @throws NoSuchElementException if the scoped value is not bound
620      */
621     @ForceInline
622     @SuppressWarnings("unchecked")
623     public T get() {
624         Object[] objects;
625         if ((objects = scopedValueCache()) != null) {
626             // This code should perhaps be in class Cache. We do it
627             // here because the generated code is small and fast and
628             // we really want it to be inlined in the caller.
629             int n = (hash & Cache.SLOT_MASK) * 2;
630             if (objects[n] == this) {
631                 return (T)objects[n + 1];
632             }
633             n = ((hash >>> Cache.INDEX_BITS) & Cache.SLOT_MASK) * 2;
634             if (objects[n] == this) {
635                 return (T)objects[n + 1];
636             }
637         }
638         return slowGet();
639     }
640 
641     @SuppressWarnings("unchecked")
642     private T slowGet() {
643         var value = findBinding();
644         if (value == Snapshot.NIL) {
645             throw new NoSuchElementException();
646         }
647         Cache.put(this, value);
648         return (T)value;
649     }
650 
651     /**
652      * {@return {@code true} if this scoped value is bound in the current thread}
653      */
654     public boolean isBound() {
655         Object[] objects = scopedValueCache();
656         if (objects != null) {
657             int n = (hash & Cache.SLOT_MASK) * 2;
658             if (objects[n] == this) {
659                 return true;
660             }
661             n = ((hash >>> Cache.INDEX_BITS) & Cache.SLOT_MASK) * 2;
662             if (objects[n] == this) {
663                 return true;
664             }
665         }
666         var value = findBinding();
667         boolean result = (value != Snapshot.NIL);
668         if (result)  Cache.put(this, value);
669         return result;
670     }
671 
672     /**
673      * Return the value of the scoped value or NIL if not bound.
674      */
675     private Object findBinding() {
676         Object value = scopedValueBindings().find(this);
677         return value;
678     }
679 
680     /**
681      * Returns the value of this scoped value if bound in the current thread, otherwise
682      * returns {@code other}.
683      *
684      * @param other the value to return if not bound, can be {@code null}
685      * @return the value of the scoped value if bound, otherwise {@code other}
686      */
687     public T orElse(T other) {
688         Object obj = findBinding();
689         if (obj != Snapshot.NIL) {
690             @SuppressWarnings("unchecked")
691             T value = (T) obj;
692             return value;
693         } else {
694             return other;
695         }
696     }
697 
698     /**
699      * Returns the value of this scoped value if bound in the current thread, otherwise
700      * throws an exception produced by the exception supplying function.
701      *
702      * @param <X> the type of the exception that may be thrown
703      * @param exceptionSupplier the supplying function that produces the exception to throw
704      * @return the value of the scoped value if bound in the current thread
705      * @throws X if the scoped value is not bound in the current thread
706      */
707     public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
708         Objects.requireNonNull(exceptionSupplier);
709         Object obj = findBinding();
710         if (obj != Snapshot.NIL) {
711             @SuppressWarnings("unchecked")
712             T value = (T) obj;
713             return value;
714         } else {
715             throw exceptionSupplier.get();
716         }
717     }
718 
719     private static Object[] scopedValueCache() {
720         return Thread.scopedValueCache();
721     }
722 
723     private static void setScopedValueCache(Object[] cache) {
724         Thread.setScopedValueCache(cache);
725     }
726 
727     // Special value to indicate this is a newly-created Thread
728     // Note that his must match the declaration in j.l.Thread.
729     private static final Object NEW_THREAD_BINDINGS = Thread.class;
730 
731     private static Snapshot scopedValueBindings() {
732         // Bindings can be in one of four states:
733         //
734         // 1: class Thread: this is a new Thread instance, and no
735         // scoped values have ever been bound in this Thread, and neither
736         // have any scoped value bindings been inherited from a parent.
737         // 2: EmptySnapshot.SINGLETON: This is effectively an empty binding.
738         // 3: A Snapshot instance: this contains one or more scoped value
739         // bindings.
740         // 4: null: there may be some bindings in this Thread, but we don't know
741         // where they are. We must invoke Thread.findScopedValueBindings() to walk
742         // the stack to find them.
743 
744         Object bindings = Thread.scopedValueBindings();
745         if (bindings == NEW_THREAD_BINDINGS) {
746             // This must be a new thread
747             return Snapshot.EMPTY_SNAPSHOT;
748         }
749         if (bindings == null) {
750             // Search the stack
751             bindings = Thread.findScopedValueBindings();
752             if (bindings == NEW_THREAD_BINDINGS || bindings == null) {
753                 // We've walked the stack without finding anything.
754                 bindings = Snapshot.EMPTY_SNAPSHOT;
755             }
756             Thread.setScopedValueBindings(bindings);
757         }
758         assert (bindings != null);
759         return (Snapshot) bindings;
760     }
761 
762     private static int nextKey = 0xf0f0_f0f0;
763 
764     // A Marsaglia xor-shift generator used to generate hashes. This one has full period, so
765     // it generates 2**32 - 1 hashes before it repeats. We're going to use the lowest n bits
766     // and the next n bits as cache indexes, so we make sure that those indexes map
767     // to different slots in the cache.
768     private static synchronized int generateKey() {
769         int x = nextKey;
770         do {
771             x ^= x >>> 12;
772             x ^= x << 9;
773             x ^= x >>> 23;
774         } while (Cache.primarySlot(x) == Cache.secondarySlot(x));
775         return (nextKey = x);
776     }
777 
778     /**
779      * Return a bit mask that may be used to determine if this ScopedValue is
780      * bound in the current context. Each Carrier holds a bit mask which is
781      * the OR of all the bit masks of the bound ScopedValues.
782      * @return the bitmask
783      */
784     int bitmask() {
785         return (1 << Cache.primaryIndex(this)) | (1 << (Cache.secondaryIndex(this) + Cache.TABLE_SIZE));
786     }
787 
788     // Return true iff bitmask, considered as a set of bits, contains all
789     // of the bits in targetBits.
790     static boolean containsAll(int bitmask, int targetBits) {
791         return (bitmask & targetBits) == targetBits;
792     }
793 
794     // A small fixed-size key-value cache. When a scoped value's get() method
795     // is invoked, we record the result of the lookup in this per-thread cache
796     // for fast access in future.
797     private static final class Cache {
798         static final int INDEX_BITS = 4;  // Must be a power of 2
799         static final int TABLE_SIZE = 1 << INDEX_BITS;
800         static final int TABLE_MASK = TABLE_SIZE - 1;
801         static final int PRIMARY_MASK = (1 << TABLE_SIZE) - 1;
802 
803         // The number of elements in the cache array, and a bit mask used to
804         // select elements from it.
805         private static final int CACHE_TABLE_SIZE, SLOT_MASK;
806         // The largest cache we allow. Must be a power of 2 and greater than
807         // or equal to 2.
808         private static final int MAX_CACHE_SIZE = 16;
809 
810         static {
811             final String propertyName = "java.lang.ScopedValue.cacheSize";
812             var sizeString = GetPropertyAction.privilegedGetProperty(propertyName, "16");
813             var cacheSize = Integer.valueOf(sizeString);
814             if (cacheSize < 2 || cacheSize > MAX_CACHE_SIZE) {
815                 cacheSize = MAX_CACHE_SIZE;
816                 System.err.println(propertyName + " is out of range: is " + sizeString);
817             }
818             if ((cacheSize & (cacheSize - 1)) != 0) {  // a power of 2
819                 cacheSize = MAX_CACHE_SIZE;
820                 System.err.println(propertyName + " must be an integer power of 2: is " + sizeString);
821             }
822             CACHE_TABLE_SIZE = cacheSize;
823             SLOT_MASK = cacheSize - 1;
824         }
825 
826         static int primaryIndex(ScopedValue<?> key) {
827             return key.hash & TABLE_MASK;
828         }
829 
830         static int secondaryIndex(ScopedValue<?> key) {
831             return (key.hash >> INDEX_BITS) & TABLE_MASK;
832         }
833 
834         private static int primarySlot(ScopedValue<?> key) {
835             return key.hashCode() & SLOT_MASK;
836         }
837 
838         private static int secondarySlot(ScopedValue<?> key) {
839             return (key.hash >> INDEX_BITS) & SLOT_MASK;
840         }
841 
842         static int primarySlot(int hash) {
843             return hash & SLOT_MASK;
844         }
845 
846         static int secondarySlot(int hash) {
847             return (hash >> INDEX_BITS) & SLOT_MASK;
848         }
849 
850         static void put(ScopedValue<?> key, Object value) {
851             Object[] theCache = scopedValueCache();
852             if (theCache == null) {
853                 theCache = new Object[CACHE_TABLE_SIZE * 2];
854                 setScopedValueCache(theCache);
855             }
856             // Update the cache to replace one entry with the value we just looked up.
857             // Each value can be in one of two possible places in the cache.
858             // Pick a victim at (pseudo-)random.
859             int k1 = primarySlot(key);
860             int k2 = secondarySlot(key);
861             var usePrimaryIndex = chooseVictim();
862             int victim = usePrimaryIndex ? k1 : k2;
863             int other = usePrimaryIndex ? k2 : k1;
864             setKeyAndObjectAt(victim, key, value);
865             if (getKey(theCache, other) == key) {
866                 setKeyAndObjectAt(other, key, value);
867             }
868         }
869 
870         private static void setKeyAndObjectAt(int n, Object key, Object value) {
871             var cache = scopedValueCache();
872             cache[n * 2] = key;
873             cache[n * 2 + 1] = value;
874         }
875 
876         private static void setKeyAndObjectAt(Object[] cache, int n, Object key, Object value) {
877             cache[n * 2] = key;
878             cache[n * 2 + 1] = value;
879         }
880 
881         private static Object getKey(Object[] objs, int n) {
882             return objs[n * 2];
883         }
884 
885         private static void setKey(Object[] objs, int n, Object key) {
886             objs[n * 2] = key;
887         }
888 
889         private static final JavaUtilConcurrentTLRAccess THREAD_LOCAL_RANDOM_ACCESS
890                 = SharedSecrets.getJavaUtilConcurrentTLRAccess();
891 
892         // Return either true or false, at pseudo-random, with a bias towards true.
893         // This chooses either the primary or secondary cache slot, but the
894         // primary slot is approximately twice as likely to be chosen as the
895         // secondary one.
896         private static boolean chooseVictim() {
897             int r = THREAD_LOCAL_RANDOM_ACCESS.nextSecondaryThreadLocalRandomSeed();
898             return (r & 15) >= 5;
899         }
900 
901         // Null a set of cache entries, indicated by the 1-bits given
902         static void invalidate(int toClearBits) {
903             toClearBits = (toClearBits >>> TABLE_SIZE) | (toClearBits & PRIMARY_MASK);
904             Object[] objects;
905             if ((objects = scopedValueCache()) != null) {
906                 for (int bits = toClearBits; bits != 0; ) {
907                     int index = Integer.numberOfTrailingZeros(bits);
908                     setKeyAndObjectAt(objects, index & SLOT_MASK, null, null);
909                     bits &= ~1 << index;
910                 }
911             }
912         }
913     }
914 }
--- EOF ---