Scope locals

Andrew Haley aph at redhat.com
Thu Jun 10 09:36:41 UTC 2021


On 6/10/21 8:43 AM, Ludovic Henry wrote:

> The user of Transaction would then switch to the following code:

```
> try (final Transaction transaction = new Transaction()) {
>  // here, Transaction.current() _does not_ return this `transaction` object.
>  transaction.run(() -> {
>   // and here, Transaction.current() _does_ return this `transaction`
> object.
>   doSomething();
>  });
> }
```

Surely this would be

Transaction.run(() -> { doSomething(); });

> The main alternative I’m seeing is for ScopeLocal to provide a TWR-like API
> in complement to the Runnable/Callable-based API. Something that could be
> used like the following:
>

 ```
> class Transaction implements AutoCloseable {
>  private static final ScopeLocal<Transaction> currentTransaction =
> ScopeLocal.forType(Transaction.class);
>  private final ScopeLocal.Context currentContext;
>  public Transaction() {
>    currentContext = ScopeLocal.where(currentTransaction,
> this).buildContext();
>  }
>  public static Transaction current() {
>   return currentTransaction.get();
>  }
>  public void close() {
>   currentContext.close();
>  }
> }
 ```

It seems to me that ThreadLocal is ideally suited to that style of
API.

One of the key requirements of scope local bindings is that they do not,
*cannot* leak into the context of a caller.  That provides both strong
security guarantees and enables the reader to reason about invariants.
One of these invariants is that scope locals are returned to their
previous values when a block ends.  Unlike the unstructured
ThreadLocals, scope local bindings have an order, and they must be
deallocated in the reverse order from which they were allocated.  This
property also guarantees that the bound value of a scope local does
not change during a method, and brings with it re-entrancy etc.

[ If we had a *strong* try-with-resources, one that didn't depend on
the user to call close(), we could do this with TWR. Ron Pressler has
some ideas in this area, TBD. When we have that working, scope locals
could use it. But right now we don't have anything. ]

So what's to be done here? If you want to be able to call a method
that sets a ThreadLocal(ish) variable, you're out of luck: that is one
of the few things scope locals cannot do.

If you can find a way to bind a scope local (which refers to a
mutable object) in an outer context, that would work too, but that
would effectively act like a ThreadLocal, shared global data.

-- 
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