Skip to content

Commit a739748

Browse files
author
Andrew Haley
committedAug 22, 2024
Scoped values API
1 parent 67bee6d commit a739748

File tree

6 files changed

+78
-149
lines changed

6 files changed

+78
-149
lines changed
 

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

+10-83
Original file line numberDiff line numberDiff line change
@@ -75,34 +75,34 @@
7575
* // @link substring="newInstance" target="#newInstance" :
7676
* private static final ScopedValue<String> NAME = ScopedValue.newInstance();
7777
*
78-
* // @link substring="runWhere" target="#runWhere(ScopedValue, Object, Runnable)" :
79-
* ScopedValue.runWhere(NAME, "duke", () -> doSomething());
78+
* // @link substring="run" target="Carrier#run(Runnable)" :
79+
* ScopedValue.where(NAME, "duke").run(() -> doSomething());
8080
* }
8181
* Code executed directly or indirectly by {@code doSomething}, with access to the field
8282
* {@code NAME}, can invoke {@code NAME.get()} to read the value "{@code duke}". {@code
8383
* NAME} is bound while executing the {@code run} method. It reverts to being unbound when
8484
* the {@code run} method completes.
8585
*
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
86+
* <p> The example using {@code run} invokes a method that does not return a result.
87+
* The {@link Carrier#call(CallableOp) call} method can be used
8888
* to invoke a method that returns a result.
89-
* In addition, {@code ScopedValue} defines the {@link #where(ScopedValue, Object)} method
89+
* {@code ScopedValue} defines the {@link #where(ScopedValue, Object)} method
9090
* for cases where multiple mappings (of {@code ScopedValue} to value) are accumulated
9191
* in advance of calling a method with all {@code ScopedValue}s bound to their value.
9292
*
9393
* <h2>Bindings are per-thread</h2>
9494
*
95-
* A {@code ScopedValue} binding to a value is per-thread. Invoking {@code xxxWhere}
95+
* A {@code ScopedValue} binding to a value is per-thread. Invoking {@code run}
9696
* executes a method with a {@code ScopedValue} bound to a value for the current thread.
9797
* The {@link #get() get} method returns the value bound for the current thread.
9898
*
9999
* <p> In the example, if code executed by one thread invokes this:
100100
* {@snippet lang=java :
101-
* ScopedValue.runWhere(NAME, "duke1", () -> doSomething());
101+
* ScopedValue.where(NAME, "duke1").run(() -> doSomething());
102102
* }
103103
* and code executed by another thread invokes:
104104
* {@snippet lang=java :
105-
* ScopedValue.runWhere(NAME, "duke2", () -> doSomething());
105+
* ScopedValue.where(NAME, "duke2").run(() -> doSomething());
106106
* }
107107
* then code in {@code doSomething} (or any method that it calls) invoking {@code NAME.get()}
108108
* will read the value "{@code duke1}" or "{@code duke2}", depending on which thread is
@@ -129,7 +129,7 @@
129129
* <p> In the above example, suppose that code executed by {@code doSomething} binds
130130
* {@code NAME} to a new value with:
131131
* {@snippet lang=java :
132-
* ScopedValue.runWhere(NAME, "duchess", () -> doMore());
132+
* ScopedValue.where(NAME, "duchess").run(() -> doMore());
133133
* }
134134
* Code executed directly or indirectly by {@code doMore()} that invokes {@code
135135
* NAME.get()} will read the value "{@code duchess}". When {@code doMore()} completes
@@ -157,7 +157,7 @@
157157
* {@snippet lang=java :
158158
* private static final ScopedValue<String> NAME = ScopedValue.newInstance();
159159
160-
* ScopedValue.runWhere(NAME, "duke", () -> {
160+
* ScopedValue.where(NAME, "duke").run(() -> {
161161
* // @link substring="open" target="StructuredTaskScope#open(Policy)" :
162162
* try (var scope = StructuredTaskScope.open(policy)) {
163163
*
@@ -414,7 +414,6 @@ public <T> T get(ScopedValue<T> key) {
414414
* @return the result
415415
* @throws StructureViolationException if a structure violation is detected
416416
* @throws X if {@code op} completes with an exception
417-
* @see ScopedValue#callWhere(ScopedValue, Object, CallableOp)
418417
* @since 23
419418
*/
420419
public <R, X extends Throwable> R call(CallableOp<? extends R, X> op) throws X {
@@ -463,7 +462,6 @@ private <R, X extends Throwable> R runWith(Snapshot newSnapshot, CallableOp<R, X
463462
*
464463
* @param op the operation to run
465464
* @throws StructureViolationException if a structure violation is detected
466-
* @see ScopedValue#runWhere(ScopedValue, Object, Runnable)
467465
*/
468466
public void run(Runnable op) {
469467
Objects.requireNonNull(op);
@@ -533,77 +531,6 @@ public static <T> Carrier where(ScopedValue<T> key, T value) {
533531
return Carrier.of(key, value);
534532
}
535533

536-
/**
537-
* Calls a value-returning operation with a {@code ScopedValue} bound to a value
538-
* in the current thread. When the operation completes (normally or with an
539-
* exception), the {@code ScopedValue} will revert to being unbound, or revert to
540-
* its previous value when previously bound, in the current thread. If {@code op}
541-
* completes with an exception then it propagated by this method.
542-
*
543-
* <p> Scoped values are intended to be used in a <em>structured manner</em>. If code
544-
* invoked directly or indirectly by the operation creates a {@link StructuredTaskScope}
545-
* but does not {@linkplain StructuredTaskScope#close() close} it, then it is detected
546-
* as a <em>structure violation</em> when the operation completes (normally or with an
547-
* exception). In that case, the underlying construct of the {@code StructuredTaskScope}
548-
* is closed and {@link StructureViolationException} is thrown.
549-
*
550-
* @implNote
551-
* This method is implemented to be equivalent to:
552-
* {@snippet lang=java :
553-
* // @link substring="call" target="Carrier#call(CallableOp)" :
554-
* ScopedValue.where(key, value).call(op);
555-
* }
556-
*
557-
*
558-
*
559-
* @param key the {@code ScopedValue} key
560-
* @param value the value, can be {@code null}
561-
* @param <T> the type of the value
562-
* @param <R> the result type
563-
* @param <X> type of the exception thrown by the operation
564-
* @param op the operation to call
565-
* @return the result
566-
* @throws StructureViolationException if a structure violation is detected
567-
* @throws X if the operation completes with an exception
568-
* @since 23
569-
*/
570-
public static <T, R, X extends Throwable> R callWhere(ScopedValue<T> key,
571-
T value,
572-
CallableOp<? extends R, X> op) throws X {
573-
return where(key, value).call(op);
574-
}
575-
576-
/**
577-
* Run an operation with a {@code ScopedValue} bound to a value in the current
578-
* thread. When the operation completes (normally or with an exception), the
579-
* {@code ScopedValue} will revert to being unbound, or revert to its previous value
580-
* when previously bound, in the current thread. If {@code op} completes with an
581-
* exception then it propagated by this method.
582-
*
583-
* <p> Scoped values are intended to be used in a <em>structured manner</em>. If code
584-
* invoked directly or indirectly by the operation creates a {@link StructuredTaskScope}
585-
* but does not {@linkplain StructuredTaskScope#close() close} it, then it is detected
586-
* as a <em>structure violation</em> when the operation completes (normally or with an
587-
* exception). In that case, the underlying construct of the {@code StructuredTaskScope}
588-
* is closed and {@link StructureViolationException} is thrown.
589-
*
590-
* @implNote
591-
* This method is implemented to be equivalent to:
592-
* {@snippet lang=java :
593-
* // @link substring="run" target="Carrier#run(Runnable)" :
594-
* ScopedValue.where(key, value).run(op);
595-
* }
596-
*
597-
* @param key the {@code ScopedValue} key
598-
* @param value the value, can be {@code null}
599-
* @param <T> the type of the value
600-
* @param op the operation to call
601-
* @throws StructureViolationException if a structure violation is detected
602-
*/
603-
public static <T> void runWhere(ScopedValue<T> key, T value, Runnable op) {
604-
where(key, value).run(op);
605-
}
606-
607534
private ScopedValue() {
608535
this.hash = generateKey();
609536
}

‎src/java.base/share/classes/java/util/concurrent/StructuredTaskScope.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -275,8 +275,8 @@
275275
* // @link substring="newInstance" target="ScopedValue#newInstance()" :
276276
* private static final ScopedValue<String> USERNAME = ScopedValue.newInstance();
277277
*
278-
* // @link substring="callWhere" target="ScopedValue#callWhere" :
279-
* Result result = ScopedValue.callWhere(USERNAME, "duke", () -> {
278+
* // @link substring="callWhere" target="ScopedValue#where" :
279+
* Result result = ScopedValue.where(USERNAME, "duke").call(() -> {
280280
*
281281
* try (var scope = StructuredTaskScope.open(Joiner.awaitAllSuccessfulOrThrow())) {
282282
*

‎src/java.base/share/classes/javax/security/auth/Subject.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -436,7 +436,7 @@ public static <T> T callAs(final Subject subject,
436436
Objects.requireNonNull(action);
437437
if (!SharedSecrets.getJavaLangAccess().allowSecurityManager()) {
438438
try {
439-
return ScopedValue.callWhere(SCOPED_SUBJECT, subject, action::call);
439+
return ScopedValue.where(SCOPED_SUBJECT, subject).call(action::call);
440440
} catch (Exception e) {
441441
throw new CompletionException(e);
442442
}

0 commit comments

Comments
 (0)