[foreign-memaccess] RFC: to scope or not to scope?

Jorn Vernee jbvernee at xs4all.nl
Mon Jun 3 22:13:26 UTC 2019


Maurizio Cimadamore schreef op 2019-06-03 22:54:
> On 01/06/2019 16:50, Jorn Vernee wrote:
>> For asConfined() creating a view segment would not work, since the 
>> root segment, which holds the liveliness flag, would not be confined 
>> to a single thread. For asConfined to work as expected I believe we 
>> would have to kill the root segment, effectively transferring the 
>> underlying resource to the newly created confined segment. This also 
>> brings up an idea I had been thinking about; make thread confined-ness 
>> a more local, temporary state. e.g. you call asConfined which creates 
>> a segment that is confined to the current thread, but then add a 
>> release() method that invalidates the confined copy and makes the root 
>> segment valid again. This could be used around loops, e.g.:
> 
> I don't think I agree with this line of thought. The use I have in
> mind for this API is something like:
> 
> try (MemorySegment segment = 
> MemorySegment.ofNative(bytes).asConfined()) { ... }
> 
> If you do this, then inside the try with resources you have the
> guarantee that everything will be confined.

This seems to be excluding the case where the MemorySegment is stored in 
a field, and then used in a loop. I'd deem that case quite likely, and I 
think there's a solution possible that works for both use-cases without 
adding too much complexity.

Also, when we have a snippet like this, the liveliness check should 
already be hoisted, assuming the loop body is also inlined, since the 
executing thread is the only one that has access to the liveliness flag.

> We could of course enforce a no-access state by default, or
> confined-by-default, but IMHO that's just adding additional hops for
> the (likely) case where these things don't make a difference. And, if
> you really want to make sure that what you have is confined, and
> there's no racy access possible, just call the view method as soon as
> you allocate the segment (as above), then nobody will be able to
> access to the non-confined version.
> 
> This is not different from how ByteBuffer::asReadOnly works - and I
> think that's a pragmatic compromise. That API too will have the same
> issues discussed here (if somebody keeps hold of the original BB, you
> can still write on a supposedly read-only buffer), but I wonder how
> much that is really a problem in practice, given that it can be
> avoided with some discipline.

Yes, but the JIT can not really assume that the programmer has this 
discipline. I'm not sure if we can prove that there's only a single 
thread accessing a segment (or rather, the liveliness flag) when this is 
not guaranteed by the API. Which would be the case if a confined segment 
is simply a view over a non-confined segment I think.

> As much as I agree with the theory that returning a no-access segment
> is the only way to make the API really tight, at the same time, I
> having factory methods that return what would effectively be unusable
> segments seems a weird API choice to me. At this point I think I would
> prefer having some 'flags' to be passed to the segment factory (pretty
> much like we had scope charateristics before).

This seems good to me for the current goal we're trying to achieve; 
making the liveliness check hoist-able. I think of the local acquire + 
release strategy as a different way to get there.

For fully fledged memory resource sharing between threads I agree with 
John that we should disallow access by multiple threads at the same 
time. So the state between allocating a segment and it being acquired by 
a single thread would be 'useless', but we could use a separate type 
that doesn't derive from MemorySegment as well for this right? That 
shouldn't be too weird...

Jorn

> Maurizio


More information about the panama-dev mailing list