No segment method for MemoryAddress?

Maurizio Cimadamore maurizio.cimadamore at oracle.com
Tue Aug 25 23:45:01 UTC 2020


On 25/08/2020 22:22, Ty Young wrote:
>
> On 8/25/20 3:40 PM, Maurizio Cimadamore wrote:
>>
>>>
>>> The libraries that I use(NVML, NVCtrl) rarely return pointers and 
>>> even when they do they are immediately made safe by my abstraction 
>>> layer:
>>>
>>>
>>> public static NativeArray<Byte> nvmlErrorString(nvmlReturn_t value) 
>>> throws Throwable
>>> {
>>>     return 
>>> NativeArray.ofUnsafeSequenceLayout((MemoryAddress)ERROR_STRING.getMethodHandle().invoke(value.getNativeValue()), 
>>> ERROR_LAYOUT);
>>> }
>>>
>>>
>>> So basically it's impossible for a MemoryAddress to not have 
>>> segment. Of course functions are an exception.
>>
>> Ok - that's what I was hinting at.
>>
>> But if that's the case - you can simply replace MemoryAddress with 
>> MemorySegment inside NativeObject and that should work as before?
>
>
> Except that doesn't work because NativeFunction(extends NativeObject) 
> doesn't have a segment, only a MemoryAddress and creating different 
> code paths is extremely ugly. Creating a method like:
>
>
> public interface NativeObject<A extends Addressable>
>
> {
>
>     public A getAddressable();
>
> }

I have to admit, I don't understand why you even bother with generics. 
Why should the user of this API (which you say it's meant to be 
high-level) should care whether a NativeObject is backed by a segment or 
an address? After all the API allows you to do dereference w/o ever 
touching a segment, and calling functions w/o method handles. So, in a 
way, these are all implementation details - and it seems odd to try so 
hard to have the API reflecting such implementation details.

In other words, I'm assuming that, as a user of your API, I really never 
need to peek at the lower level and deal with MemoryAddress and 
MemorySegment directly, right? If that's the case, then I'd suggest that 
dropping the generic type argument is ok, and perhaps even dropping the 
"getAddressable" is ok; if you want to keep that for interop with other 
libraries using memory segments (but here I have to admit I'm starting 
to lose sight of the goal you are trying to achieve), then perhaps just 
exposing something which returns an Addressable (and leave the user to 
cast it) is ok.

Or, you can always use covariant overriding:

interface NativeObject {
    public Addressable addressable();
}

interface NativeStruct extends NativeObject {
    public MemorySegment addressable();
}

interface NativeFunction extends NativeObject {
    public MemoryAddress addressable();
}

No type-variables here, and yet the types are sharp. Perhaps something 
like this might work. I don't think you really need to expose sharp 
distinction such as that between mapped segments and native segments, 
but if you do then I have to admit I don't understand how the API is 
supposed to be used.

Maurizio





More information about the panama-dev mailing list