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