Scoped variables: a rough first draft

Ron Pressler ron.pressler at oracle.com
Thu Aug 22 13:10:58 UTC 2019


The general approach is compatible with what we had in mind, except for one important difference:
Scope variables must not be mutable. Immutability will allow us to cleanly “inherit” scope variables
in multiple strands inside a FiberScope.

Ron


On August 21, 2019 at 4:42:27 PM, Andrew Haley (aph at redhat.com) wrote:

Here's my thinking:  


In a (very) abstract world, we'd want something like  

class MyHolderClass {  
scoped X myVar;  
}  

which provides a name for a variable but allocates no storage for it.  

Note that all of the usual Java access rules apply. If the declaration  
of MyHolderClass.myVar isn't accessible, neither are any of its bound  
values.  

When we want to use one of these variables, we'll first have to bind  
it to some storage. I suggest something like this:  

{  
bind myVar;  
...  
... invocations ...  
...  
}  

At this point the variable has a binding, but has not not been  
assigned a value. Conceptually, this scoped variable's value now has a  
storage location but has no value.  

From this point onwards, accesses to MyHolderClass.myVar will refer to  
the innermost bound binding. Assignments to unbound scoped variables  
will raise an exception.  

Note that the scope search order is *dynamic*. So, if we have a bunch  
of nested continuations, the binding used is the innermost one that is  
found in the current stack. So, if a carrier thread binds a scoped  
variable, it will be visible to all continuations running on that  
stack.  

So why search the dynamic scopes, not the scopes in existence when the  
continuations where created? Two reasons:  

1. We can't guarantee that the creation-time binding scope will still  
exist when the continuation is executed.  

2. If we need continuations to inherit from the context at creation  
time, we already have mechanisms to do that. What we don't have is a  
way to access the dynamic scope, which is what this mechanism  
provides.  

I'm writing a rough (and very inefficient) patch which does something  
like this, albeit in a not-very-efficient way. Here's what it looks  
like.  

The declaration of a scoped variable is  

class MyHolderClass {  
static final ScopedVariable<X> myVar = ScopedVariable.forType(X.class);  
}  

To create a binding I've used try-with-resources:  

try (ScopedVariableBinding<X> b = myVar.bind()) {  
...  
... invocations ...  
...  
}  

And in place of assignments and accesses,  

myVar.get(), myVar.set()  

There are some weaknesses in this approximation of the abstract idea,  
in particular that we can't enforce the binding scope. But never mind,  
that can be fixed later. The (lack of) efficiency can be fixed too.  

So, he says with some trepidation, is this basically sane? :-)  

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