1 /*
2 * Copyright (c) 2020, 2023, 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
47 *
48 * <p> In the Java programming language, data is usually passed to a method by means of a
49 * method parameter. The data may need to be passed through a sequence of many methods to
50 * get to the method that makes use of the data. Every method in the sequence of calls
51 * needs to declare the parameter and every method has access to the data.
52 * {@code ScopedValue} provides a means to pass data to a faraway method (typically a
53 * <em>callback</em>) without using method parameters. In effect, a {@code ScopedValue}
54 * is an <em>implicit method parameter</em>. It is "as if" every method in a sequence of
55 * calls has an additional parameter. None of the methods declare the parameter and only
56 * the methods that have access to the {@code ScopedValue} object can access its value
57 * (the data). {@code ScopedValue} makes it possible to securely pass data from a
58 * <em>caller</em> to a faraway <em>callee</em> through a sequence of intermediate methods
59 * that do not declare a parameter for the data and have no access to the data.
60 *
61 * <p> The {@code ScopedValue} API works by executing a method with a {@code ScopedValue}
62 * object <em>bound</em> to some value for the bounded period of execution of a method.
63 * The method may invoke another method, which in turn may invoke another. The unfolding
64 * execution of the methods define a <em>dynamic scope</em>. Code in these methods with
65 * access to the {@code ScopedValue} object may read its value. The {@code ScopedValue}
66 * object reverts to being <em>unbound</em> when the original method completes normally or
67 * with an exception. The {@code ScopedValue} API supports executing a {@link Runnable#run()
68 * Runnable.run}, {@link Callable#call() Callable.call}, or {@link Supplier#get() Supplier.get}
69 * method with a {@code ScopedValue} bound to a value.
70 *
71 * <p> Consider the following example with a scoped value "{@code NAME}" bound to the value
72 * "{@code duke}" for the execution of a {@code run} method. The {@code run} method, in
73 * turn, invokes {@code doSomething}.
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" :
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, Callable) callWhere} and {@link
88 * #getWhere(ScopedValue, Object, Supplier) getWhere} can be used to invoke a method that
89 * returns a result.
90 * In addition, {@code ScopedValue} defines the {@link #where(ScopedValue, Object)} method
91 * for cases where multiple mappings (of {@code ScopedValue} to value) are accumulated
92 * in advance of calling a method with all {@code ScopedValue}s bound to their value.
93 *
94 * <h2>Bindings are per-thread</h2>
95 *
96 * A {@code ScopedValue} binding to a value is per-thread. Invoking {@code xxxWhere}
97 * executes a method with a {@code ScopedValue} bound to a value for the current thread.
98 * The {@link #get() get} method returns the value bound for the current thread.
99 *
100 * <p> In the example, if code executed by one thread invokes this:
101 * {@snippet lang=java :
102 * ScopedValue.runWhere(NAME, "duke1", () -> doSomething());
103 * }
104 * and code executed by another thread invokes:
105 * {@snippet lang=java :
106 * ScopedValue.runWhere(NAME, "duke2", () -> doSomething());
107 * }
108 * then code in {@code doSomething} (or any method that it calls) invoking {@code NAME.get()}
109 * will read the value "{@code duke1}" or "{@code duke2}", depending on which thread is
274 int bits = key.bitmask();
275 for (Snapshot snapshot = this;
276 containsAll(snapshot.bitmask, bits);
277 snapshot = snapshot.prev) {
278 for (Carrier carrier = snapshot.bindings;
279 carrier != null && containsAll(carrier.bitmask, bits);
280 carrier = carrier.prev) {
281 if (carrier.getKey() == key) {
282 Object value = carrier.get();
283 return value;
284 }
285 }
286 }
287 return NIL;
288 }
289 }
290
291 /**
292 * A mapping of scoped values, as <em>keys</em>, to values.
293 *
294 * <p> A {@code Carrier} is used to accumulate mappings so that an operation (a
295 * {@link Runnable} or {@link Callable}) can be executed with all scoped values in the
296 * mapping bound to values. The following example runs an operation with {@code k1}
297 * bound (or rebound) to {@code v1}, and {@code k2} bound (or rebound) to {@code v2}.
298 * {@snippet lang=java :
299 * // @link substring="where" target="#where(ScopedValue, Object)" :
300 * ScopedValue.where(k1, v1).where(k2, v2).run(() -> ... );
301 * }
302 *
303 * <p> A {@code Carrier} is immutable and thread-safe. The {@link
304 * #where(ScopedValue, Object) where} method returns a new {@code Carrier} object,
305 * it does not mutate an existing mapping.
306 *
307 * <p> Unless otherwise specified, passing a {@code null} argument to a method in
308 * this class will cause a {@link NullPointerException} to be thrown.
309 *
310 * @since 21
311 */
312 @PreviewFeature(feature = PreviewFeature.Feature.SCOPED_VALUES)
313 public static final class Carrier {
314 // Bit masks: a 1 in postion n indicates that this set of bound values
315 // hits that slot in the cache.
316 final int bitmask;
317 final ScopedValue<?> key;
318 final Object value;
319 final Carrier prev;
320
366 ScopedValue<?> getKey() {
367 return key;
368 }
369
370 /**
371 * Returns the value of a {@link ScopedValue} in this mapping.
372 *
373 * @param key the {@code ScopedValue} key
374 * @param <T> the type of the value
375 * @return the value
376 * @throws NoSuchElementException if the key is not present in this mapping
377 */
378 @SuppressWarnings("unchecked")
379 public <T> T get(ScopedValue<T> key) {
380 var bits = key.bitmask();
381 for (Carrier carrier = this;
382 carrier != null && containsAll(carrier.bitmask, bits);
383 carrier = carrier.prev) {
384 if (carrier.getKey() == key) {
385 Object value = carrier.get();
386 return (T)value;
387 }
388 }
389 throw new NoSuchElementException();
390 }
391
392 /**
393 * Calls a value-returning operation with each scoped value in this mapping bound
394 * to its value in the current thread.
395 * When the operation completes (normally or with an exception), each scoped value
396 * in the mapping will revert to being unbound, or revert to its previous value
397 * when previously bound, in the current thread. If {@code op} completes with an
398 * exception then it propagated by this method.
399 *
400 * <p> Scoped values are intended to be used in a <em>structured manner</em>. If code
401 * invoked directly or indirectly by the operation creates a {@link StructuredTaskScope}
402 * but does not {@linkplain StructuredTaskScope#close() close} it, then it is detected
403 * as a <em>structure violation</em> when the operation completes (normally or with an
404 * exception). In that case, the underlying construct of the {@code StructuredTaskScope}
405 * is closed and {@link StructureViolationException} is thrown.
406 *
407 * @param op the operation to run
408 * @param <R> the type of the result of the operation
409 * @return the result
410 * @throws StructureViolationException if a structure violation is detected
411 * @throws Exception if {@code op} completes with an exception
412 * @see ScopedValue#callWhere(ScopedValue, Object, Callable)
413 */
414 public <R> R call(Callable<? extends R> op) throws Exception {
415 Objects.requireNonNull(op);
416 Cache.invalidate(bitmask);
417 var prevSnapshot = scopedValueBindings();
418 var newSnapshot = new Snapshot(this, prevSnapshot);
419 return runWith(newSnapshot, op);
420 }
421
422 /**
423 * Invokes a supplier of results with each scoped value in this mapping bound
424 * to its value in the current thread.
425 * When the operation completes (normally or with an exception), each scoped value
426 * in the mapping will revert to being unbound, or revert to its previous value
427 * when previously bound, in the current thread. If {@code op} completes with an
428 * exception then it propagated by this method.
429 *
430 * <p> Scoped values are intended to be used in a <em>structured manner</em>. If code
431 * invoked directly or indirectly by the operation creates a {@link StructuredTaskScope}
432 * but does not {@linkplain StructuredTaskScope#close() close} it, then it is detected
433 * as a <em>structure violation</em> when the operation completes (normally or with an
434 * exception). In that case, the underlying construct of the {@code StructuredTaskScope}
435 * is closed and {@link StructureViolationException} is thrown.
436 *
437 * @param op the operation to run
438 * @param <R> the type of the result of the operation
439 * @return the result
440 * @throws StructureViolationException if a structure violation is detected
441 * @see ScopedValue#getWhere(ScopedValue, Object, Supplier)
442 */
443 public <R> R get(Supplier<? extends R> op) {
444 Objects.requireNonNull(op);
445 Cache.invalidate(bitmask);
446 var prevSnapshot = scopedValueBindings();
447 var newSnapshot = new Snapshot(this, prevSnapshot);
448 return runWith(newSnapshot, new CallableAdapter<R>(op));
449 }
450
451 // A lightweight adapter from Supplier to Callable. This is
452 // used here to create the Callable which is passed to
453 // Carrier#call() in this thread because it needs neither
454 // runtime bytecode generation nor any release fencing.
455 private static final class CallableAdapter<V> implements Callable<V> {
456 private /*non-final*/ Supplier<? extends V> s;
457 CallableAdapter(Supplier<? extends V> s) {
458 this.s = s;
459 }
460 public V call() {
461 return s.get();
462 }
463 }
485
486 /**
487 * Runs an operation with each scoped value in this mapping bound to its value
488 * in the current thread.
489 * When the operation completes (normally or with an exception), each scoped value
490 * in the mapping will revert to being unbound, or revert to its previous value
491 * when previously bound, in the current thread. If {@code op} completes with an
492 * exception then it propagated by this method.
493 *
494 * <p> Scoped values are intended to be used in a <em>structured manner</em>. If code
495 * invoked directly or indirectly by the operation creates a {@link StructuredTaskScope}
496 * but does not {@linkplain StructuredTaskScope#close() close} it, then it is detected
497 * as a <em>structure violation</em> when the operation completes (normally or with an
498 * exception). In that case, the underlying construct of the {@code StructuredTaskScope}
499 * is closed and {@link StructureViolationException} is thrown.
500 *
501 * @param op the operation to run
502 * @throws StructureViolationException if a structure violation is detected
503 * @see ScopedValue#runWhere(ScopedValue, Object, Runnable)
504 */
505 public void run(Runnable op) {
506 Objects.requireNonNull(op);
507 Cache.invalidate(bitmask);
508 var prevSnapshot = scopedValueBindings();
509 var newSnapshot = new Snapshot(this, prevSnapshot);
510 runWith(newSnapshot, op);
511 }
512
513 /**
514 * Execute the action with a set of {@code ScopedValue} bindings.
515 *
516 * The VM recognizes this method as special, so any changes to the
517 * name or signature require corresponding changes in
518 * JVM_FindScopedValueBindings().
519 */
520 @Hidden
521 @ForceInline
522 private void runWith(Snapshot newSnapshot, Runnable op) {
523 try {
524 Thread.setScopedValueBindings(newSnapshot);
525 Thread.ensureMaterializedForStackWalk(newSnapshot);
526 ScopedValueContainer.run(op);
527 } finally {
528 Reference.reachabilityFence(newSnapshot);
529 Thread.setScopedValueBindings(newSnapshot.prev);
530 Cache.invalidate(bitmask);
531 }
532 }
533 }
534
535 /**
536 * Creates a new {@code Carrier} with a single mapping of a {@code ScopedValue}
537 * <em>key</em> to a value. The {@code Carrier} can be used to accumulate mappings so
538 * that an operation can be executed with all scoped values in the mapping bound to
539 * values. The following example runs an operation with {@code k1} bound (or rebound)
540 * to {@code v1}, and {@code k2} bound (or rebound) to {@code v2}.
541 * {@snippet lang=java :
542 * // @link substring="run" target="Carrier#run(Runnable)" :
543 * ScopedValue.where(k1, v1).where(k2, v2).run(() -> ... );
544 * }
545 *
546 * @param key the {@code ScopedValue} key
547 * @param value the value, can be {@code null}
548 * @param <T> the type of the value
549 * @return a new {@code Carrier} with a single mapping
550 */
551 public static <T> Carrier where(ScopedValue<T> key, T value) {
552 return Carrier.of(key, value);
553 }
554
555 /**
556 * Calls a value-returning operation with a {@code ScopedValue} bound to a value
557 * in the current thread. When the operation completes (normally or with an
558 * exception), the {@code ScopedValue} will revert to being unbound, or revert to
559 * its previous value when previously bound, in the current thread. If {@code op}
560 * completes with an exception then it propagated by this method.
561 *
562 * <p> Scoped values are intended to be used in a <em>structured manner</em>. If code
563 * invoked directly or indirectly by the operation creates a {@link StructuredTaskScope}
564 * but does not {@linkplain StructuredTaskScope#close() close} it, then it is detected
565 * as a <em>structure violation</em> when the operation completes (normally or with an
566 * exception). In that case, the underlying construct of the {@code StructuredTaskScope}
567 * is closed and {@link StructureViolationException} is thrown.
568 *
569 * @implNote
570 * This method is implemented to be equivalent to:
571 * {@snippet lang=java :
572 * // @link substring="call" target="Carrier#call(Callable)" :
573 * ScopedValue.where(key, value).call(op);
574 * }
575 *
576 * @param key the {@code ScopedValue} key
577 * @param value the value, can be {@code null}
578 * @param <T> the type of the value
579 * @param <R> the result type
580 * @param op the operation to call
581 * @return the result
582 * @throws StructureViolationException if a structure violation is detected
583 * @throws Exception if the operation completes with an exception
584 */
585 public static <T, R> R callWhere(ScopedValue<T> key,
586 T value,
587 Callable<? extends R> op) throws Exception {
588 return where(key, value).call(op);
589 }
590
591 /**
592 * Invokes a supplier of results with a {@code ScopedValue} bound to a value
593 * in the current thread. When the operation completes (normally or with an
594 * exception), the {@code ScopedValue} will revert to being unbound, or revert to
595 * its previous value when previously bound, in the current thread. If {@code op}
596 * completes with an exception then it propagated by this method.
597 *
598 * <p> Scoped values are intended to be used in a <em>structured manner</em>. If code
599 * invoked directly or indirectly by the operation creates a {@link StructuredTaskScope}
600 * but does not {@linkplain StructuredTaskScope#close() close} it, then it is detected
601 * as a <em>structure violation</em> when the operation completes (normally or with an
602 * exception). In that case, the underlying construct of the {@code StructuredTaskScope}
603 * is closed and {@link StructureViolationException} is thrown.
604 *
605 * @implNote
606 * This method is implemented to be equivalent to:
607 * {@snippet lang=java :
608 * // @link substring="get" target="Carrier#get(Supplier)" :
609 * ScopedValue.where(key, value).get(op);
610 * }
611 *
612 * @param key the {@code ScopedValue} key
613 * @param value the value, can be {@code null}
614 * @param <T> the type of the value
615 * @param <R> the result type
616 * @param op the operation to call
617 * @return the result
618 * @throws StructureViolationException if a structure violation is detected
619 */
620 public static <T, R> R getWhere(ScopedValue<T> key,
621 T value,
622 Supplier<? extends R> op) {
623 return where(key, value).get(op);
624 }
625
626 /**
627 * Run an operation with a {@code ScopedValue} bound to a value in the current
628 * thread. When the operation completes (normally or with an exception), the
629 * {@code ScopedValue} will revert to being unbound, or revert to its previous value
630 * when previously bound, in the current thread. If {@code op} completes with an
631 * exception then it propagated by this method.
632 *
633 * <p> Scoped values are intended to be used in a <em>structured manner</em>. If code
634 * invoked directly or indirectly by the operation creates a {@link StructuredTaskScope}
635 * but does not {@linkplain StructuredTaskScope#close() close} it, then it is detected
636 * as a <em>structure violation</em> when the operation completes (normally or with an
637 * exception). In that case, the underlying construct of the {@code StructuredTaskScope}
638 * is closed and {@link StructureViolationException} is thrown.
639 *
640 * @implNote
641 * This method is implemented to be equivalent to:
642 * {@snippet lang=java :
643 * // @link substring="run" target="Carrier#run(Runnable)" :
644 * ScopedValue.where(key, value).run(op);
645 * }
646 *
647 * @param key the {@code ScopedValue} key
648 * @param value the value, can be {@code null}
649 * @param <T> the type of the value
650 * @param op the operation to call
651 * @throws StructureViolationException if a structure violation is detected
652 */
653 public static <T> void runWhere(ScopedValue<T> key, T value, Runnable op) {
654 where(key, value).run(op);
655 }
656
657 private ScopedValue() {
658 this.hash = generateKey();
659 }
660
661 /**
662 * Creates a scoped value that is initially unbound for all threads.
663 *
664 * @param <T> the type of the value
665 * @return a new {@code ScopedValue}
666 */
667 public static <T> ScopedValue<T> newInstance() {
668 return new ScopedValue<T>();
669 }
670
671 /**
672 * {@return the value of the scoped value if bound in the current thread}
673 *
674 * @throws NoSuchElementException if the scoped value is not bound
675 */
676 @ForceInline
|
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
47 *
48 * <p> In the Java programming language, data is usually passed to a method by means of a
49 * method parameter. The data may need to be passed through a sequence of many methods to
50 * get to the method that makes use of the data. Every method in the sequence of calls
51 * needs to declare the parameter and every method has access to the data.
52 * {@code ScopedValue} provides a means to pass data to a faraway method (typically a
53 * <em>callback</em>) without using method parameters. In effect, a {@code ScopedValue}
54 * is an <em>implicit method parameter</em>. It is "as if" every method in a sequence of
55 * calls has an additional parameter. None of the methods declare the parameter and only
56 * the methods that have access to the {@code ScopedValue} object can access its value
57 * (the data). {@code ScopedValue} makes it possible to securely pass data from a
58 * <em>caller</em> to a faraway <em>callee</em> through a sequence of intermediate methods
59 * that do not declare a parameter for the data and have no access to the data.
60 *
61 * <p> The {@code ScopedValue} API works by executing a method with a {@code ScopedValue}
62 * object <em>bound</em> to some value for the bounded period of execution of a method.
63 * The method may invoke another method, which in turn may invoke another. The unfolding
64 * execution of the methods define a <em>dynamic scope</em>. Code in these methods with
65 * access to the {@code ScopedValue} object may read its value. The {@code ScopedValue}
66 * object reverts to being <em>unbound</em> when the original method completes normally or
67 * with an exception. The {@code ScopedValue} API supports executing a {@link Runnable},
68 * {@link Callable}, or {@link Supplier} with a {@code ScopedValue} bound to a value.
69 *
70 * <p> Consider the following example with a scoped value "{@code NAME}" bound to the value
71 * "{@code duke}" for the execution of a {@code run} method. The {@code run} method, in
72 * turn, invokes {@code doSomething}.
73 * {@snippet lang=java :
74 * // @link substring="newInstance" target="#newInstance" :
75 * private static final ScopedValue<String> NAME = ScopedValue.newInstance();
76 *
77 * // @link substring="runWhere" target="#runWhere(ScopedValue, Object, Runnable)" :
78 * ScopedValue.runWhere(NAME, "duke", () -> doSomething());
79 * }
80 * Code executed directly or indirectly by {@code doSomething}, with access to the field
81 * {@code NAME}, can invoke {@code NAME.get()} to read the value "{@code duke}". {@code
82 * NAME} is bound while executing the {@code run} method. It reverts to being unbound when
83 * the {@code run} method completes.
84 *
85 * <p> The example using {@code runWhere} invokes a method that does not return a result.
86 * The {@link #callWhere(ScopedValue, Object, Callable) callWhere} and {@link
87 * #getWhere(ScopedValue, Object, Supplier) getWhere} methods can be used to invoke a
88 * 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
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}, {@link Callable} or {@link Supplier}) can be executed with all scoped
295 * values in the mapping bound to values. The following example runs an operation with
296 * {@code k1} bound (or rebound) to {@code v1}, and {@code k2} bound (or rebound) to
297 * {@code v2}.
298 * {@snippet lang=java :
299 * ScopedValue.runWhere(ScopedValue.where(k1, v1).where(k2, v2), () -> ... );
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
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 * @return the result
409 * @throws StructureViolationException if a structure violation is detected
410 * @throws Exception if {@code op} completes with an exception
411 * @see ScopedValue#callWhere(ScopedValue, Object, Callable)
412 */
413 <R> R call(Callable<? extends R> op) throws Exception {
414 Objects.requireNonNull(op);
415 Cache.invalidate(bitmask);
416 var prevSnapshot = scopedValueBindings();
417 var newSnapshot = new Snapshot(this, prevSnapshot);
418 return runWith(newSnapshot, op);
419 }
420
421 /**
422 * Invokes a supplier of results with each scoped value in this mapping bound
423 * to its value in the current thread.
424 * When the operation completes (normally or with an exception), each scoped value
425 * in the mapping will revert to being unbound, or revert to its previous value
426 * when previously bound, in the current thread. If {@code op} completes with an
427 * exception then it propagated by this method.
428 *
429 * <p> Scoped values are intended to be used in a <em>structured manner</em>. If code
430 * invoked directly or indirectly by the operation creates a {@link StructuredTaskScope}
431 * but does not {@linkplain StructuredTaskScope#close() close} it, then it is detected
432 * as a <em>structure violation</em> when the operation completes (normally or with an
433 * exception). In that case, the underlying construct of the {@code StructuredTaskScope}
434 * is closed and {@link StructureViolationException} is thrown.
435 *
436 * @param op the operation to run
437 * @param <R> the type of the result of the operation
438 * @return the result
439 * @throws StructureViolationException if a structure violation is detected
440 * @see ScopedValue#getWhere(ScopedValue, Object, Supplier)
441 */
442 <R> R get(Supplier<? extends R> op) {
443 Objects.requireNonNull(op);
444 Cache.invalidate(bitmask);
445 var prevSnapshot = scopedValueBindings();
446 var newSnapshot = new Snapshot(this, prevSnapshot);
447 return runWith(newSnapshot, new CallableAdapter<R>(op));
448 }
449
450 // A lightweight adapter from Supplier to Callable. This is
451 // used here to create the Callable which is passed to
452 // Carrier#call() in this thread because it needs neither
453 // runtime bytecode generation nor any release fencing.
454 private static final class CallableAdapter<V> implements Callable<V> {
455 private /*non-final*/ Supplier<? extends V> s;
456 CallableAdapter(Supplier<? extends V> s) {
457 this.s = s;
458 }
459 public V call() {
460 return s.get();
461 }
462 }
484
485 /**
486 * Runs an operation with each scoped value in this mapping bound to its value
487 * in the current thread.
488 * When the operation completes (normally or with an exception), each scoped value
489 * in the mapping will revert to being unbound, or revert to its previous value
490 * when previously bound, in the current thread. If {@code op} completes with an
491 * exception then it propagated by this method.
492 *
493 * <p> Scoped values are intended to be used in a <em>structured manner</em>. If code
494 * invoked directly or indirectly by the operation creates a {@link StructuredTaskScope}
495 * but does not {@linkplain StructuredTaskScope#close() close} it, then it is detected
496 * as a <em>structure violation</em> when the operation completes (normally or with an
497 * exception). In that case, the underlying construct of the {@code StructuredTaskScope}
498 * is closed and {@link StructureViolationException} is thrown.
499 *
500 * @param op the operation to run
501 * @throws StructureViolationException if a structure violation is detected
502 * @see ScopedValue#runWhere(ScopedValue, Object, Runnable)
503 */
504 void run(Runnable op) {
505 Objects.requireNonNull(op);
506 Cache.invalidate(bitmask);
507 var prevSnapshot = scopedValueBindings();
508 var newSnapshot = new Snapshot(this, prevSnapshot);
509 runWith(newSnapshot, op);
510 }
511
512 /**
513 * Execute the action with a set of {@code ScopedValue} bindings.
514 *
515 * The VM recognizes this method as special, so any changes to the
516 * name or signature require corresponding changes in
517 * JVM_FindScopedValueBindings().
518 */
519 @Hidden
520 @ForceInline
521 private void runWith(Snapshot newSnapshot, Runnable op) {
522 try {
523 Thread.setScopedValueBindings(newSnapshot);
524 Thread.ensureMaterializedForStackWalk(newSnapshot);
525 ScopedValueContainer.run(op);
526 } finally {
527 Reference.reachabilityFence(newSnapshot);
528 Thread.setScopedValueBindings(newSnapshot.prev);
529 Cache.invalidate(bitmask);
530 }
531 }
532 }
533
534 /**
535 * Creates a new {@code Carrier} with a single mapping of a {@code ScopedValue}
536 * <em>key</em> to a value. The {@code Carrier} can be used to accumulate mappings so
537 * that an operation can be executed with all scoped values in the mapping bound to
538 * values. The following example runs an operation with {@code k1} bound (or rebound)
539 * to {@code v1}, and {@code k2} bound (or rebound) to {@code v2}.
540 * {@snippet lang=java :
541 * // @link substring="runWhere" target="#runWhere(Carrier, Runnable)" :
542 * ScopedValue.runWhere(ScopedValue.where(k1, v1).where(k2, v2), () -> ... );
543 * }
544 *
545 * @param key the {@code ScopedValue} key
546 * @param value the value, can be {@code null}
547 * @param <T> the type of the value
548 * @return a new {@code Carrier} with a single mapping
549 */
550 public static <T> Carrier where(ScopedValue<T> key, T value) {
551 return Carrier.of(key, value);
552 }
553
554 /**
555 * Calls a value-returning operation with a {@code ScopedValue} bound to a value
556 * in the current thread. When the operation completes (normally or with an
557 * exception), the {@code ScopedValue} will revert to being unbound, or revert to
558 * its previous value when previously bound, in the current thread. If {@code op}
559 * completes with an exception then it propagated by this method.
560 *
561 * <p> Scoped values are intended to be used in a <em>structured manner</em>. If code
562 * invoked directly or indirectly by the operation creates a {@link StructuredTaskScope}
563 * but does not {@linkplain StructuredTaskScope#close() close} it, then it is detected
564 * as a <em>structure violation</em> when the operation completes (normally or with an
565 * exception). In that case, the underlying construct of the {@code StructuredTaskScope}
566 * is closed and {@link StructureViolationException} is thrown.
567 *
568 * @param key the {@code ScopedValue} key
569 * @param value the value, can be {@code null}
570 * @param <T> the type of the value
571 * @param <R> the result type
572 * @param op the operation to call
573 * @return the result
574 * @throws StructureViolationException if a structure violation is detected
575 * @throws Exception if the operation completes with an exception
576 */
577 public static <T, R> R callWhere(ScopedValue<T> key,
578 T value,
579 Callable<? extends R> op) throws Exception {
580 return where(key, value).call(op);
581 }
582
583 /**
584 * Calls a value-returning operation with each scoped value in the given mapping bound
585 * to its value in the current thread.
586 * When the operation completes (normally or with an exception), each scoped value
587 * in the mapping will revert to being unbound, or revert to its previous value
588 * when previously bound, in the current thread. If {@code op} completes with an
589 * exception then it propagated by this method.
590 *
591 * <p> Scoped values are intended to be used in a <em>structured manner</em>. If code
592 * invoked directly or indirectly by the operation creates a {@link StructuredTaskScope}
593 * but does not {@linkplain StructuredTaskScope#close() close} it, then it is detected
594 * as a <em>structure violation</em> when the operation completes (normally or with an
595 * exception). In that case, the underlying construct of the {@code StructuredTaskScope}
596 * is closed and {@link StructureViolationException} is thrown.
597 *
598 * @param carrier the mapping of scoped values, as keys, to values
599 * @param op the operation to run
600 * @return the result
601 * @param <R> the result type
602 * @throws StructureViolationException if a structure violation is detected
603 * @throws Exception if the operation completes with an exception
604 * @since 23
605 */
606 public static <R> R callWhere(Carrier carrier,
607 Callable<? extends R> op) throws Exception {
608 return carrier.call(op);
609 }
610
611 /**
612 * Invokes a supplier of results with a {@code ScopedValue} bound to a value
613 * in the current thread. When the operation completes (normally or with an
614 * exception), the {@code ScopedValue} will revert to being unbound, or revert to
615 * its previous value when previously bound, in the current thread. If {@code op}
616 * completes with an exception then it propagated by this method.
617 *
618 * <p> Scoped values are intended to be used in a <em>structured manner</em>. If code
619 * invoked directly or indirectly by the operation creates a {@link StructuredTaskScope}
620 * but does not {@linkplain StructuredTaskScope#close() close} it, then it is detected
621 * as a <em>structure violation</em> when the operation completes (normally or with an
622 * exception). In that case, the underlying construct of the {@code StructuredTaskScope}
623 * is closed and {@link StructureViolationException} is thrown.
624 *
625 * @param key the {@code ScopedValue} key
626 * @param value the value, can be {@code null}
627 * @param <T> the type of the value
628 * @param <R> the result type
629 * @param op the operation to call
630 * @return the result
631 * @throws StructureViolationException if a structure violation is detected
632 */
633 public static <T, R> R getWhere(ScopedValue<T> key,
634 T value,
635 Supplier<? extends R> op) {
636 return where(key, value).get(op);
637 }
638
639 /**
640 * Invokes a supplier of results with each scoped value in the given mapping bound
641 * to its value in the current thread.
642 * When the operation completes (normally or with an exception), each scoped value
643 * in the mapping will revert to being unbound, or revert to its previous value
644 * when previously bound, in the current thread. If {@code op} completes with an
645 * exception then it propagated by this method.
646 *
647 * <p> Scoped values are intended to be used in a <em>structured manner</em>. If code
648 * invoked directly or indirectly by the operation creates a {@link StructuredTaskScope}
649 * but does not {@linkplain StructuredTaskScope#close() close} it, then it is detected
650 * as a <em>structure violation</em> when the operation completes (normally or with an
651 * exception). In that case, the underlying construct of the {@code StructuredTaskScope}
652 * is closed and {@link StructureViolationException} is thrown.
653 *
654 * @param carrier the mapping of scoped values, as keys, to values
655 * @param op the operation to run
656 * @return the result
657 * @param <R> the result type
658 * @throws StructureViolationException if a structure violation is detected
659 * @since 23
660 */
661 public static <R> R getWhere(Carrier carrier, Supplier<? extends R> op) {
662 return carrier.get(op);
663 }
664
665 /**
666 * Run an operation with a {@code ScopedValue} bound to a value in the current
667 * thread. When the operation completes (normally or with an exception), the
668 * {@code ScopedValue} will revert to being unbound, or revert to its previous value
669 * when previously bound, in the current thread. If {@code op} completes with an
670 * exception then it propagated by this method.
671 *
672 * <p> Scoped values are intended to be used in a <em>structured manner</em>. If code
673 * invoked directly or indirectly by the operation creates a {@link StructuredTaskScope}
674 * but does not {@linkplain StructuredTaskScope#close() close} it, then it is detected
675 * as a <em>structure violation</em> when the operation completes (normally or with an
676 * exception). In that case, the underlying construct of the {@code StructuredTaskScope}
677 * is closed and {@link StructureViolationException} is thrown.
678 *
679 * @param key the {@code ScopedValue} key
680 * @param value the value, can be {@code null}
681 * @param <T> the type of the value
682 * @param op the operation to call
683 * @throws StructureViolationException if a structure violation is detected
684 */
685 public static <T> void runWhere(ScopedValue<T> key, T value, Runnable op) {
686 where(key, value).run(op);
687 }
688
689 /**
690 * Runs an operation with each scoped value in the given mapping bound to its value
691 * in the current thread.
692 * When the operation completes (normally or with an exception), each scoped value
693 * in the mapping will revert to being unbound, or revert to its previous value
694 * when previously bound, in the current thread. If {@code op} completes with an
695 * exception then it propagated by this method.
696 *
697 * <p> Scoped values are intended to be used in a <em>structured manner</em>. If code
698 * invoked directly or indirectly by the operation creates a {@link StructuredTaskScope}
699 * but does not {@linkplain StructuredTaskScope#close() close} it, then it is detected
700 * as a <em>structure violation</em> when the operation completes (normally or with an
701 * exception). In that case, the underlying construct of the {@code StructuredTaskScope}
702 * is closed and {@link StructureViolationException} is thrown.
703 *
704 * @param carrier the mapping of scoped values, as keys, to values
705 * @param op the operation to run
706 * @throws StructureViolationException if a structure violation is detected
707 * @since 23
708 */
709 public static void runWhere(Carrier carrier, Runnable op) {
710 carrier.run(op);
711 }
712
713 private ScopedValue() {
714 this.hash = generateKey();
715 }
716
717 /**
718 * Creates a scoped value that is initially unbound for all threads.
719 *
720 * @param <T> the type of the value
721 * @return a new {@code ScopedValue}
722 */
723 public static <T> ScopedValue<T> newInstance() {
724 return new ScopedValue<T>();
725 }
726
727 /**
728 * {@return the value of the scoped value if bound in the current thread}
729 *
730 * @throws NoSuchElementException if the scoped value is not bound
731 */
732 @ForceInline
|