<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  </head>
  <body>
    <p>Hi Chris,<br>
      thanks for the comments.</p>
    <p>First of all, I agree the javadoc needs more verbiage around what
      can happen when `close` is not supported.</p>
    <p>Regarding your question, there are many reasons which has led us
      towards leaving `isCloseable` out - at least for now.</p>
    <p>First, the semantics of `isCloseable` is a bit ambiguous: should
      it mean "can I call close on this arena?", or should it mean "is
      this arena associated with a bounded lifetime" ? The two questions
      aren't the same: in the first case you are asking about a property
      of a specific `Arena::close` method (will it throw
      UnsupportedOperationException?); in the other case you are asking
      about an intrinsic property of the lifetime backing the arena. For
      instance, an automatic arena has a bounded lifetime, but its
      `close` method still throws. Perhaps, the solution here would be
      to have a method which deal with `close` in Arena, and then
      another method in MemorySegment.Scope which tells whether a scope
      is "bounded" or not.</p>
    <p>Secondly, as explained in the document, custom arenas muddy the
      picture quite a bit, as it is not clear as to whether
      `isCloseable` should just always delegate to the parent arena
      `isCloseable`, or if a subclass can redefine it in interesting
      ways - e.g. a client might wrap a closeable arena into a new arena
      whose close method always throws - at which point the
      `isCloseable` method could be overridden to return false. But
      IMHO, it is hard to reason about custom arenas because it is not
      clear what we mean by `isCloseable` (see above).<br>
    </p>
    <p>Finally, all our usages analysis have shown that, so far, of all
      the code using the Java 19 API (which has a
      MemorySession::isCloseable predicate) we didn't find any
      significant usages (only one usage was found in an assert in the
      Netty code :-)). This seems to suggest that these predicates are
      not only hard to nail down semantics-wise, they also don't seem to
      be used much. I think I can understand why: typically code that
      has a MemorySession/Arena has created it, so it _knows_ what are
      the properties of that session/arena.</p>
    <p>For this reasons, I find your example a bit on the contrived
      side: two clients exchange segments/arenas - which means they are
      under the same maintenance domain (otherwise client B would not
      have access to arenas). The way I'd approach the situation you
      describe would be to put resources in distinct arenas. Clearly you
      have identified cases as to why some resources are tied with the
      lifetime of a single request (e.g. local resources) whereas other
      resources can be reused across multiple requests (e.g. global or
      cached resources). To me, this suggests that there should be an
      Arena for what B wants to do. The code in B is always surrounded
      with a try-with-resources (at least logically - in practice the
      lifetime can start in A and end with B), so that all the resources
      that are "local" to B get released when B is done. But "global"
      resources are simply passed in (e.g. using some context object) -
      and B is not expected to invalidate them (nor it can't because
      they are backed by an arena it can't control).</p>
    <p>In other words, my feeling here is that the need for
      `isCloseable` arises because A and B simply exchange
      segments/arenas in a fairly unstructured way, but - as you say -
      not all segments in this communication are created equal. Which
      suggests that the communication protocol between A and B should be
      made a bit more sophisticated, so that B can distinguish between
      local and global resources.</p>
    <p>But, even w/o making things overly complex, something like this
      should work:</p>
    <p>```<br>
      B::process(Arena sessionArena, MemorySegment[] segments)<br>
      ```<br>
    </p>
    <p>Here, B has a bunch of segments to work with. Some will be backed
      by `sessionArena` (which B is expected to close anyway at the end
      of its computation). Some will be backed by some other arena -
      which means they will survive the `process` method. This way, B
      always knows how to operate: it should work on the received
      segments and then call `sessionArena.close()` when done. Note that
      A could even inject custom close logic on `sessionArena`, by
      providing an arena with an overridden close method. This might be
      useful if the segments that should be closed in reality might
      belong to multiple arenas, all of which should be closed (or when
      custom cleanup logic should be executed by A). But I think an API
      like this makes it easier to understand how B is expected to
      operate.</p>
    <p>That said, I don't want to dismiss your concern - but I do
      believe that a "wait and see" approach is a sane way to proceed:
      future code will inform us as to whether such predicates are
      needed or not (and _where_ should such predicates live - e.g. in
      Arena vs. MemorySegment.Scope).</p>
    <p>Cheers<br>
      Maurizio<br>
    </p>
    <br>
    <div class="moz-cite-prefix">On 05/02/2023 19:56, Chris Vest wrote:<br>
    </div>
    <blockquote type="cite" cite="mid:CAHXi_0cJXKDgZJahibbjTYeTJ5sYwcJZZfX-hF+qxDqgA-jM=Q@mail.gmail.com">
      
      <div dir="ltr">Hi,
        <div><br>
        </div>
        <div>This looks like a good and simple API overall, with a clear
          path on how each individual use case is solved.</div>
        <div><br>
        </div>
        <div>I found that details of the behavior of Arena.close() were
          lacking in the API description, now that we are back to having
          close methods on things that can't be closed:</div>
        <div>It is not described what happens when you call close() on
          global and auto scoped arenas. I also see no mechanism for
          querying if an arena has one of these scopes.</div>
        <div>The document says it's unclear what isCloseable() should
          return for an arena where close() always throws. I'm not so
          sure.</div>
        <div>I think the query could be framed as "if I were to call
          close(), is it likely to succeed?" (I use "likely" here since
          shared scopes could race).</div>
        <div><br>
        </div>
        <div>To illustrate where this might be relevant, suppose we have
          web application with a component A in charge of formulating
          responses to clients, and another component B in charge of
          doing IO.</div>
        <div>Component A sends MemorySegments and Arenas to B, and these
          could be a mix of shared or confined scopes, and auto-scoped
          for cached data like images and CSS files.</div>
        <div>Lifetimes start in A, but only conditionally end in B. This
          will need to be tracked, since the arenas and scopes can't be
          queried for this information.</div>
        <div>While this is certainly possible, it seems like a wasteful
          step, as the arena ought to have this knowledge in order to
          implement close() itself.</div>
        <div><br>
        </div>
        <div>This is the only thing I'm wondering about. The rest of the
          API looks very good.</div>
        <div><br>
        </div>
        <div>Cheers,</div>
        <div>Chris</div>
      </div>
      <br>
      <div class="gmail_quote">
        <div dir="ltr" class="gmail_attr">On Tue, Jan 31, 2023 at 10:46
          AM Maurizio Cimadamore <<a href="mailto:maurizio.cimadamore@oracle.com" moz-do-not-send="true" class="moz-txt-link-freetext">maurizio.cimadamore@oracle.com</a>>
          wrote:<br>
        </div>
        <blockquote class="gmail_quote" style="margin:0px 0px 0px
0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex">Hi,<br>
          as discussed here [1], it is not clear as to whether Java 20
          iteration <br>
          of the Foreign Function & Memory API (FFM API) has yet
          reached bottom, <br>
          especially when it comes to managing the lifetime of the
          regions of <br>
          memory backing memory segments. After collecting some rounds
          of internal <br>
          and external feedback, it was clear that while the Java 20 API
          has all <br>
          the functionalities we require for writing efficient and
          robust native <br>
          interop code, some of the concepts in the API were made a bit
          harder to <br>
          grok, as users had to choose between two toplevel
          abstractions, namely <br>
          `SegmentScope` and `Arena`. This choice is made even more
          difficult, as <br>
          some of the functionalities (e.g. allocation) is duplicated in
          both API <br>
          points. As a result, we have been busy exploring different
          ways to <br>
          restack the FFM API in search of something more approachable.<br>
          <br>
          The results of our findings are described in this document:<br>
          <br>
          <a href="http://cr.openjdk.java.net/~mcimadamore/panama/scoped_arenas.html" rel="noreferrer" target="_blank" moz-do-not-send="true" class="moz-txt-link-freetext">http://cr.openjdk.java.net/~mcimadamore/panama/scoped_arenas.html</a><br>
          <br>
          Here, we propose a possible simplification of the FFM API,
          where we make <br>
          `Arena` the true star of the show, which results in the
          following changes:<br>
          <br>
          * factories such as `SegmentScope::auto` are now moved to
          `Arena`;<br>
          * all segment-producing methods (such as `FileChannel::map`)
          now accept <br>
          an `Arena` parameter;<br>
          * static factories such as `MemorySegment::allocateNative`
          have been <br>
          dropped;<br>
          * scopes are made less prominent, and moved to a nested class
          <br>
          (`MemorySegment.Scope`).<br>
          <br>
          This gives us a remarkably simple API, which brings together
          the best <br>
          aspects of the Java 19 and Java 20 FFM API iterations. On the
          one hand, <br>
          `Arena` is now the most important abstraction that users of
          the FFM API <br>
          have to deal with (in a way, `Arena` is the new
          `MemorySession`); at the <br>
          same time, we still have a way to model the lifetime of an
          `Arena` (and <br>
          all the segments allocated by it) using a
          `MemorySegment.Scope` - which <br>
          is desirable both in terms of debugging (e.g. inspecting
          whether two <br>
          segments/arenas have the same lifetime) and, more importantly,
          in terms <br>
          of allowing the definition of custom arenas via simple
          delegation (as in <br>
          Java 20).<br>
          <br>
          As always, feedback is welcome. While this proposal does not <br>
          significantly alter the expressiveness of the FFM API, the
          proposed API <br>
          comes with some limitations. For instance, since all
          allocation routines <br>
          are now `Arena`-centric (see above), it is no longer possible
          to <br>
          allocate a new segment if a corresponding arena is not
          available (we <br>
          call this co-allocation). As explained in the document, while
          it would <br>
          be possible to add back the missing co-allocation
          functionality, <br>
          extensive analysis of the code using the FFM API has shown
          co-allocation <br>
          to be _extremely_ rare (**) - and of dubious value. For these
          reasons, <br>
          we would like to aim for a more principled approach which
          avoids <br>
          co-allocation altogether, and allows for more encapsulation of
          the <br>
          capabilities associated with an `Arena` object.<br>
          <br>
          Maurizio<br>
          <br>
          (**) We have only found _one_ usage [2] in over 10K Java files
          and more <br>
          than 11M LoC analyzed. Moreover, this usage is only present in
          the Java <br>
          19 branch of the project, and removed in the "main" branch
          (which tracks <br>
          the Java 20 FFM API). We suspect that this use of
          co-allocation has been <br>
          made irrelevant after the unification of `MemoryAddress` and <br>
          `MemorySegment`.<br>
          <br>
          [1] - <br>
          <a href="https://mail.openjdk.org/pipermail/panama-dev/2022-December/018182.html" rel="noreferrer" target="_blank" moz-do-not-send="true" class="moz-txt-link-freetext">https://mail.openjdk.org/pipermail/panama-dev/2022-December/018182.html</a><br>
          [2] - <br>
          <a href="https://urldefense.com/v3/__https://github.com/boulder-on/JPassport/blob/Java_19/jpassport/src/main/java/jpassport/Utils.java*L418__;Iw!!ACWV5N9M2RV99hQ!MB7MDEPjnE7sfsm2kjOWvsGp1DN6u1XAGyMAzkjSdZw7-11yWTo39B6YRtcK8gPYPZ-5ZlaeI3KxuCT3F5flAIOvAA9yWQ$" rel="noreferrer" target="_blank" moz-do-not-send="true">https://github.com/boulder-on/JPassport/blob/Java_19/jpassport/src/main/java/jpassport/Utils.java#L418</a><br>
          <br>
          <br>
          <br>
          <br>
          <br>
          <br>
        </blockquote>
      </div>
    </blockquote>
  </body>
</html>