on scope accessors (Was Re: changes to the foreign preview API)

Maurizio Cimadamore maurizio.cimadamore at oracle.com
Fri Feb 11 15:02:41 UTC 2022


On 01/02/2022 12:48, Maurizio Cimadamore wrote:
> The other change we'd like to make is to remove the scope()  > accessors from all the resources (MemorySegment, NativeSymbol, > 
VaList). This comes from a desire to make the API more principled: > 
only the owner of a scope/session should have the "right" to close > it. 
In fact, we have spent significant API estate (e.g. > 
ResourceScope::whileAlive) just from preventing random clients to > shut 
down scopes. We now believe a better approach would be to simply > make 
the scope associated e.g. with a memory segment inaccessible. In > other 
words, a resource scope/memory session becomes a _capability_: > it is 
up to the owner of the scope/session to decide who to share > that 
capability with. Once a client has a scope, it can close that > scope, 
but also affect the scope by registering cleanup actions, or > 
allocating on that scope. Conversely, if a client only has a segment, > 
there's no way for that client to affect the owning scope/session in > a 
meaninful (and possibly, harmful) way.
Thinking some more on this, removing scope() accessor from segments can 
indeed be problematic (at least if not counterbalanced by any other API 
move), in at least three different ways:

1. it makes creating "dependent" segments harder (this is the issue 
reported by Michael in [1]); that is (morally) nested segments that 
should have same lifetime as some enclosing segment.
2. it makes it hard to reason about scope invariants: for instance, when 
setting an inner segment into an outer segment you might want to check 
that the scopes are compatible.
3. aside from "dependent" segment, it is sometimes helpful to create 
"copies" of existing segments, with same lifetime properties (this is 
something we encountered in VaList::copy).

Without a scope accessor, none of the above operations is possible, 
unless the code performing the operation has a scope handy. While some 
ad-hoc solution could be possible for (1), I think the other problems 
are harder to address - and I find (2) particularly problematic.

As previously discussed, one possible solution is to always pass a scope 
to abstractions that need to perform any of the above operations. But I 
fear this might be error prone, as it will likely result in code that 
looks like this:

```
StructFoo.create(MemorySegment.ofAddress(addr, 10, scope), scope); // 
note duplication of "scope"
```

Or we could, of course, leave everything as is - just rename the 
abstraction (from ResourceScope to MemorySession) and then keep a 
session accessor on MemorySegment, NativeSymbol and VaList, and give up 
on the desire to restrict access to the ResourceScope::close method.

But, after exploring some alternatives, I think there is a simple 
solution which gives us what we want (e.g. defend against calls to close 
methods from "unprivileged" clients) w/o changing the API too much; the 
solution consists exposing an extra flag on MemorySession/ResourceScope 
which says whether the scope/session can be closed explicitly. If we 
have that, we are in a position to have MemorySegment::session (and 
other similar methods) just return a non-closeable _view_ of the session 
they are associated with. Of course this also means giving up to 
identity comparison and use equals() instead, but I think that's pretty 
straightforward. In addition to address our original problem, the new 
flag can also be used to denote sessions that cannot be closed, such as 
the global session, or implicit, GC-backed sessions.

With this change, existing code should basically still compile and work 
as expected; the only thing disallowed being:

```
segment.session().close()
```

Here's a javadoc of the proposed changes:

http://cr.openjdk.java.net/~mcimadamore/panama/session_preview/javadoc/java.base/java/lang/foreign/package-summary.html

And here's a branch, should you want to look at code changes:

https://github.com/mcimadamore/panama-foreign/commits/session_preview

I plan to start a PR for this soon.

Maurizio


[1] - 
https://mail.openjdk.java.net/pipermail/panama-dev/2022-February/016164.html






More information about the panama-dev mailing list