musinig on close actions
Michael Zucchi
notzed at gmail.com
Fri Feb 25 22:11:16 UTC 2022
Morning Maurizio,
FWIW I've been busy with summer of late and taking a break from this
stuff. And as a result I haven't yet explored the previously discussed
ideas fully so my comments might not be worth a lot.
But my initial thought on this is 'looks like it should work but it
seems a bit over-engineered'.
I guess my overall feeling on scopes is that they're "almost right" but
one always seems to end up hitting cases that don't match how they
operate and this just seems to be another special casing of one of
those. I can see in general the problem is difficult due to java vs
native lifecycle differences. Even where Java has existing explicit
close such as with AutoClosable and Closeable there are implementation
complexities, mostly due to those also being native resources.
I did have some thoughts on a problem related to the nested-ish-scopes
of opencl and vulkan, but I didn't get around to fleshing them out
enough to articulate it properly. Like it would be nice to have some
sort of ligtweight/threaded/nested scope that could apply to individual
or small groups of objects, but i vaguely remember scopes used to work
like a bit like this initially but it got changed due to complexity
and/or inflexibility. But again this seems like another case of
impedance mismatch with the resourcescope as-it-is-currently-defined.
Regards,
Michael
On 19/2/22 05:56, Maurizio Cimadamore wrote:
> Hi,
> I wanted to capture some thoughts on scope close actions, which
> originated from the good discussions we had in [1].
>
> Basically, the status quo is that a close action is called _after_ the
> scope is closed. This is a forced move: when we execute the close
> action, we already have determined that e.g. the scope is not accessed
> by any other thread. If resources were still accessible by close
> actions, then closing a scope would not be safe (as they could be
> leaked to other threads).
>
> There is a minor inconvenience with this approach: if a close action
> needs to refer to some of the resources associated with the scope
> (e.g. a segment), the action needs to work on the resource using its
> memory address, thus losing safety and also expressiveness (e.g. to
> use var handles you need a memory segment). This was the issue pointed
> out in [1] with the FFmpeg API. There are other situations in which
> working on segments, rather than addresses, might be preferrable: for
> instance, one can come up with an API which turns an heap segment into
> an off-heap segment, inside a given scope (e.g. pinning). In certain
> cases where pinning is not supported directly by the GC, it might be
> required to copy the contents of the native segment back to the
> on-heap segment once the scope is closed. But if the segment is not
> alive after close, there's no way to do the copy.
>
> I've been toying with an idea, which builds upon the following two
> observations:
>
> 1. Resource-specific close actions are likely to arise when using the
> `MemorySegment::ofAddress` methods (or any of the `XYZ::ofAddress`
> factories)
>
> 2. A close action could safely operate on a *view* of the half-alive
> resource based on a "closingScope" which is confined on the thread
> that does the closing
>
> The API move that I have in mind is this: let's assume that we added
> an overload to `MemorySegment`, as follows:
>
> ```
> static MemorySegment ofAddress(MemoryAddress addr, long size,
> MemorySession session, Consumer<MemorySegment> cleanupAction)
> ```
>
> Which can be used as follows:
>
> ```
> MemoryAddress addr = ....
> MemorySegment segment = MemorySegment.ofAddress(addr, 10L, session,
> segmentView -> println(segmentView.get(JAVA_DOUBLE,
> offset)));
> ```
>
> How does this work? After a scope transitions into the closed state,
> but _before_ cleanup actions are called, the scope would spawn a _new_
> _confined_ scope, owned by the thread from which cleanup action are
> called. That scope is then used to create resource views that will be
> passed to the close actions. The new session is then closed after
> _all_ the close actions have been executed.
> Crucially, since all views are confined and cannot be accessed after
> `MemorySession::close()` completes, this works out ok safety-wise, I
> believe. In a way, this is a restricted form of safe handoff of a
> resource, from one scope to another. This allows clients to express
> close actions at the right level of abstraction, without the need to
> give up safety/expressiveness and drop down to `MemoryAddress`.
>
> Please note that I'm not proposing to drop support for "global" close
> actions (e.g. the `MemorySession::addCloseAction` method). These are
> still useful in many cases, as we've seen for pooled allocators [2].
> So the above mechanism would be an addition to the API, rather than a
> replacement (and one that can also be considered at a later point, if
> needs be).
>
> Any thoughts on whether something like this could help?
>
> Cheers
> Maurizio
>
> [1] -
> https://mail.openjdk.java.net/pipermail/panama-dev/2022-February/016173.html
> [2] - https://github.com/openjdk/panama-foreign/pull/509
More information about the panama-dev
mailing list