ScopedValue.runWhere not returning scope

Andrew Haley aph-open at littlepinkcloud.com
Tue Jun 11 12:35:44 UTC 2024


On 6/11/24 11:32, Marcin Grzejszczak wrote:

 >> So why not produce an example of how it would be used? As far as I can
 >> see, your proposal fails to ensure the property in the case I posted/
 >
 > I've created samples at the very beginning with the before and after
 > interceptor. I obviously know that I could rewrite the interceptor
 > to become an around one but my point is that it's not an ideal
 > solution to require instrumentors to rewrite everything. Also I
 > still see this whole discussion as having two ways of doing the same
 > thing. Current approach:
 >
 > ScopedValue.runWhere(scopedValue, someValue, () -> {
 >        codeToRun();
 >      });
 >
 > Proposed approach:
 >
 > try(Scope scope = ScopedValue.openScope(scopedValue, someValue)) {
 >    codeToRun();

This API fails the test I provided:

    final ScopedValue aScopedValue = ...;
    final var x = aScopedValue.get();
    ScopedValue.openScope(aScopedValue, someValue);
    final var y = aScopedValue.get();

    assert(x == y); // Always succeeds

In other words, scoped values would no longer be strictly scoped.
That's what the "scoped" means in the name "scoped values". Strict
scoping is a fundamental property.

 > }
 >
 > I understand that in the proposed approach one can mess things up, I
 > really do. But library instrumentors and tracing library creators
 > would benefit from that sort of API.

If we were planning to deprecate thread-local variables I think this
argument might have some merit. But we're not. They're not going away.

 > Also I've asked a different question... What if the users want to
 > leverage the ScopedValues to get the current span information (or
 > current principal from security point of view) but also they are
 > using TL based libraries? How would the interop look like?

As the JEP says, scoped values do not replace all uses of thread-local
variables. There are still some cases where thread-local variables
will be used, and this looks like one of them.

 > Let's assume that they put into the current scope a span that they
 > want to have within that scope, we would need all the tracer
 > libraries (and security components and others that use the same
 > mechanism) to be ScopeValue aware. Would they first try to read SV
 > and then if that's not there a TL?

Yes, I think so.

 > They would need to most likely read SV and populate TL if the SV
 > value is present so that other components that still rely on TL
 > would work. That would have to also work the other way round, if a
 > TL based library sets a value (e.g. span) then maybe the ScopedValue
 > should be created with a scope for that new value?

I'm not sure how that'd work in general, but there's nothing to stop
entry points for a library from doing so, and it might be a good idea.
Something like:

     if (someThreadLocal.get() != NOTHING) {
         where(someScopedValue, someThreadLocal.get()).run(realEntry);
     } else {
         realEntry.run();
     }

-- 
Andrew Haley  (he/him)
Java Platform Lead Engineer
Red Hat UK Ltd. <https://www.redhat.com>
https://keybase.io/andrewhaley
EAC8 43EB D3EF DB98 CC77 2FAD A5CD 6035 332F A671



More information about the loom-dev mailing list