[foreign-abi] RFR: JDK-8243669: Improve library loading for Panama libraries

Samuel Audet samuel.audet at gmail.com
Fri May 1 09:57:41 UTC 2020


On 4/30/20 7:07 PM, Maurizio Cimadamore wrote:
>> Right, it's not perfect, but I think these kinds of issues are 
>> solvable, if we're willing to spend time and work on them. For 
>> example, if something like `PointerScope` could be integrated into the 
>> Java language itself, we would be able to guarantee that what you 
>> describe above never happens, making everything thread-safe. I don't 
>> see any limitations in that regards, but I may be missing something. 
>> Could you provide an example that fails? Or is there just concern 
>> about the performance hit that could be incurred (in which case I'd 
>> still say "let's work on it")?
> 
> This is the very central issue we're trying to address with memory 
> segments: how do you allow access to a segment from multiple threads while:
> 
> * retaining access performances
> * retaining deterministic deallocation guarantees
> 
> It's not a theoretical problem. If you want to make your JavaCPP code 
> safe you need to add a mutex so that threads can either access memory OR 
> deallocate. Then I'm sure you won't be happy with the numbers that will 
> come out of your benchmarks.
> 
> Other solutions "include" something like reference counting, but not the 
> same reference counting you do in your API. That is, if a thread wants 
> to use a "pointer" (in your API) you must create a new instance just for 
> that thread, you can't just increment some shared counter on the 
> original pointer. That is, the _new_ thread must _not_ have access to 
> the original pointer. Otherwise it is possible for people to write code 
> where they don't call "retain" and they happily access the pointer from 
> multiple threads, but the pointer doesn't know about it.
> 
> While something like that might be made to work (we had something 
> similar with our MemorySegment::acquire), it is not very appealing from 
> an API perspective, as it creates "trees" of associated 
> segments/pointers where the parent cannot be deallocated until all 
> children are.
> 
> All this to say what I was trying to say before: wrapping up 
> AtomicInteger inside some ARC abstraction is _not_ a solution to the 
> problem. First, it doesn't really take that long to implement,  but, 
> most importantly, having a class which can do "retain"/"release" doesn't 
> save you from uncooperative clients trying to use an instance from a 
> different thread w/o calling "retain".
> 
> So, I don't see a lot of value for providing such an abstraction in the 
> JDK. The fact that there are libaries out there which might rely on 
> reference counting to provide some sort of perceived safety doesn't 
> automatically make this a candidate for providing something with the 
> degree of safety that would (and should) be expected from a Java SE API.

Thank you for bearing with me, but I must seriously be missing 
something. Please explain why the following doesn't work:

Main Thread:
{
// some "global" scope
Pointer p = // some constructor
// code emitted by the compiler increments counter of p
p.initSomeMore()
// start threads, etc
// code emitted by the compiler decrements counter of p
}

Thread 1:
// some "local" scope
{
// code emitted by the compiler increments counter of p
p.doSomething()
// code emitted by the compiler decrements counter of p
}

Thread 2:
// some other "local" scope
{
// code emitted by the compiler increments counter of p
p.doSomethingElse()
// code emitted by the compiler decrements counter of p
}

We have only one instance of the object, while locks, if they are 
required, only need to happen when accessing the reference counter. The 
user *does not* have access to the counter, it *cannot* be manually 
incremented or decremented. I'm not saying this is easy to implement 
into something meaningful, but I don't see where the roadblocks are.

Samuel


More information about the panama-dev mailing list