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