[foreign-memaccess] RFR 8227394: Add MemorySegment::asByteBuffer convenience method
Jorn Vernee
jbvernee at xs4all.nl
Fri Jul 12 15:26:55 UTC 2019
Here is the updated version:
http://cr.openjdk.java.net/~jvernee/panama/webrevs/8227394/webrev.04/
* Moved asByteBuffer to MemorySegment
* Added an offset() getter to MemoryAddress
* Updated tests to use the new asByteBuffer where possible (all but one)
* Renamed ForeignUnsafe methods to getUnsafeOffset and getUnsafeBase
FWIW, negative offsets are required in some cases, so I think offset()
is better than advance().
Jorn
On 2019-07-11 18:55, Maurizio Cimadamore wrote:
> On 11/07/2019 17:51, Maurizio Cimadamore wrote:
>>
>>> This sounds good as well.
>>>
>>> I was thinking about the lump/split discussion around MA and MS,
>>> particularly where we draw the lines of responsibility between the
>>> two. I think MS should be used to manage a memory resource
>>> (allocating, slicing, closing), while MA should simply be used to
>>> access the resource (dereferencing, offset). So, after all, I think
>>> any method for slicing the segment (i.e. managing the resource)
>>> should be in MS as well.
>>>
>>> I'm not so sure about the name offset() though, since that seems to
>>> clash a bit with ForeignUnsafe::getOffset(), and
>>> MemoryAddress::offset(long). Maybe an alternative is offsetOf(), or
>>> toSegmentOffset()?
>>
>> We have other cases in the JDK where the same name is used for getter
>> and setter (e.g. ByteBuffer::order). So I'm not overly worried about
>> that, and I still prefer that that using get/set.
>
> Actually, virtually all methods here
>
> https://docs.oracle.com/en/java/javase/12/docs/api/java.base/java/nio/Buffer.html
>
> use that pattern. So, while not super-ideal, I think that could be
> justified.
>
> As for the unsafe methods, I think we should rename them to
> getUnsafeOffset and getUnsafeBase
>
> Maurizio
>
>
>>
>> Another option worth looking into would be, IMHO, to explore
>> alternatives for the offset(long) method. In a way it feels the use of
>> offset is ambiguous here, it is both a noun (which justifies the
>> getter semantics) and a verb (which justifies the setter/wither
>> semantics). For instance, one possible renaming for offset(long) is
>> advance/move
>>
>> address.advance(42).offset();
>>
>> I think that reads well? (also implies that negative offsets are kind
>> of not accepted?)
>>
>> Maurizio
>>
>>>
>>> Jorn
>>>
>>>> Maurizio
>>>>
>>>>
>>>>>
>>>>> Like you say, by adding a MemorySegment::asByteBuffer we introduce
>>>>> a problem because some segments are too large, but this seems
>>>>> pretty similar to being able to pass a size to
>>>>> MemoryAddress::asByteBuffer that is too large, which is still
>>>>> possible even if it's an `int`. At the same time we have one less
>>>>> problem because we can no longer use a MemoryAddress that is out of
>>>>> bounds of the segment.
>>>>>
>>>>> It feels like a pretty much even trade.
>>>>>
>>>>>> I'm less convinced on the
>>>>>> usefulness of turning an entire memory segment into a bytebuffer:
>>>>>> if
>>>>>> you really wanted to view the entire memory segment as a BB, maybe
>>>>>> you
>>>>>> just wanted to create a (direct) BB in the first place?
>>>>>
>>>>> By that same line of thought, do we need
>>>>> MemoryAddress::asByteBuffer? This is meant as an interop thing,
>>>>> where you just have a MemorySegment that is given to you, and would
>>>>> like to turn it into a ByteBuffer.
>>>>>
>>>>> I agree with the concern of the API explosion. I was also looking
>>>>> at removing the asByteBuffer method from MemoryAddress, and
>>>>> replacing it with a more general 'sliceAt' method, that slices the
>>>>> underlying MemorySegment at the offset denoted by the MemoryAddress
>>>>> itself (instead of having to pass that manually as the offset to
>>>>> MemorySegment::slice). I could imagine cases where a user has a
>>>>> MemoryAddress and wants to do an offset and then slice, e.g. I have
>>>>> a pointer to some struct, returned by some third party allocator
>>>>> API, and want to give someone else a pointer to access just a
>>>>> single field, I can try and call `address.segment().slice(...)`,
>>>>> but the problem would be that I don't know what to pass as offset
>>>>> (after all, the MemoryAddress I have might not be the base address
>>>>> of the segment).
>>>>>
>>>>> With a `sliceAt` method, the current use of asByteBuffer(int) could
>>>>> be replaced with `address.sliceAt(newSize).asByteBuffer()`.
>>>>>
>>>>> Prototype:
>>>>> http://cr.openjdk.java.net/~jvernee/panama/webrevs/8227394/webrev.01/
>>>>>
>>>>> What do you think? Of course, if you'd rather hold off on fiddling
>>>>> with the API too much at this time that's fine with me :) (I'm
>>>>> guessing we're trying to target JDK 14 as an incubating feature?)
>>>>>
>>>>> Jorn
>>>>>
>>>>> On 2019-07-11 14:00, Maurizio Cimadamore wrote:
>>>>>> Hi Jorn,
>>>>>> I gave some thought about this in the past, and my conclusion was
>>>>>> mixed - and I filed this in the "you ain't gonna need it" bucket
>>>>>> (YAGNI).
>>>>>>
>>>>>> The motivations are that (i) it is really simple to emulate the
>>>>>> API
>>>>>> with the existing methods (as the implementation of the new method
>>>>>> shows), and that (ii) the new API is, by necessity, a partial API
>>>>>> -
>>>>>> not all segments can be mapped onto a byte buffer - some are too
>>>>>> large; while the existing API on memory address is total (thanks
>>>>>> to
>>>>>> the explicit int parameter).
>>>>>>
>>>>>> In other words, the existing API on MemoryAddress supports what I
>>>>>> believe to be the most important interop idiom: slicing a big
>>>>>> memory
>>>>>> segment into multiple < 32bits buffer views. I'm less convinced on
>>>>>> the
>>>>>> usefulness of turning an entire memory segment into a bytebuffer:
>>>>>> if
>>>>>> you really wanted to view the entire memory segment as a BB, maybe
>>>>>> you
>>>>>> just wanted to create a (direct) BB in the first place?
>>>>>>
>>>>>> The current model is kind of easy to explain - the moves we allow
>>>>>> are:
>>>>>>
>>>>>> * ByteBuffer -> MemorySegment
>>>>>>
>>>>>> * MemoryAddress + int -> ByteBuffer
>>>>>>
>>>>>> This feels minimal. If we add another dimension, as per your
>>>>>> patch:
>>>>>>
>>>>>> * MemorySegment -> ByteBuffer
>>>>>>
>>>>>> Then the next question is - should we allow also:
>>>>>>
>>>>>> * ByteBuffer -> MemoryAddress? (e.g. create a big segment from the
>>>>>> byte buffer and then have a memory address point at the BB offset)
>>>>>>
>>>>>> Which feels a bit like a slippery slope. I'd be more confident in
>>>>>> adding a facility like this after some real world validation.
>>>>>>
>>>>>> What do you think?
>>>>>>
>>>>>> Maurizio
>>>>>>
>>>>>> On 11/07/2019 12:28, Jorn Vernee wrote:
>>>>>>> Hi,
>>>>>>>
>>>>>>> Please review this small patch that adds an asByteBuffer
>>>>>>> convenience method to MemorySegment that returns a buffer the
>>>>>>> size of the segment.
>>>>>>>
>>>>>>> Bug: https://bugs.openjdk.java.net/browse/JDK-8227394
>>>>>>> Webrev:
>>>>>>> http://cr.openjdk.java.net/~jvernee/panama/webrevs/8227394/webrev.00/
>>>>>>> (note that the javadoc is largely taken from
>>>>>>> MemoryAddress::asByteBuffer).
>>>>>>>
>>>>>>> My reason for adding this is that I wanted to reach for this
>>>>>>> method a few times when playing with the API, but it didn't
>>>>>>> exist. So, I thought it would be useful to have.
>>>>>>>
>>>>>>> (Also, I originally wanted to upload this to GitHub [1] to test
>>>>>>> out the Skara [2] tools, but apparently that's not operational
>>>>>>> yet :) )
>>>>>>>
>>>>>>> Thanks,
>>>>>>> Jorn
>>>>>>>
>>>>>>> [1] : https://github.com/openjdk/panama/pull/1
>>>>>>> [2] : https://github.com/openjdk/skara#openjdk-project-skara
More information about the panama-dev
mailing list