On 23/02/2026 14: 18, Michael Stover wrote: > Secondly, the propagation of ScopedValues in StructuredConcurrency is > nice, but it's limited to simply copying the reference to the > ScopedValue to all the sub-threads.   For some purposes,
On 23/02/2026 14:18, Michael Stover wrote:
> Secondly, the propagation of ScopedValues in StructuredConcurrency is 
> nice, but it's limited to simply copying the reference to the 
> ScopedValue to all the sub-threads.  For some purposes, that works fine, 
> but there are surely cases where what we'd want is a child context 
> created, probably from the parent.

By design, no copying takes place. The set of scoped value bindings is 
made visible to the child. That set is immutable: nothing in it can be 
altered, and nothing can be removed. When a child thread is started 
there is no opportunity to inspect the inherited bindings to determine 
any properties. All a child can do is create a superset of the parent's 
bindings by adding bindings of its own.

> If the propagation routine could discover that a ScopedValue would 
> prefer to create a child scoped value rather than just copying the 
> parent scoped value to all sub-threads, then when creating a ScopedValue 
> we could control how it propagates.  If the ScopedValue implemented an 
> interface  such as "PropagatingScopedValue" or whatever, then it could 
> have the opportunity to create it's child object for each sub-thread.

The ScopedValue API is deliberately simple, in order to have a small API 
surface and to impose as little as possible runtime overhead on simple 
usage patterns.

We didn't implement a non-inheritable scoped value because that's fairly 
simple to do in user code.

public class MyKindOfScopedValue<T> {

     private final ScopedValue<ValueHolder<T> > handle;

     public MyKindOfScopedValue() {
         handle = ScopedValue.newInstance();
     }

     public void runWith(T t, Runnable op) {
         where(value, new ValueHolder(t)).run(op);
     }

     public T get() {
         return handle.get().get();
     }

     ... etc
}

class ValueHolder<T> {
     private final Thread owner;
     private final T value;

     T get() {
         if (owner == Thread.currentThread()) {
             return value;
         } else {
             ... something local here;
         }
     }

     ValueHolder(T value) {
         owner = Thread.currentThread();
         this.value = value;
     }

     ... etc
}

Reply via email to