On 4/29/20 11:16 PM, Maurizio Cimadamore wrote:

On 29/04/2020 21:40, Maurizio Cimadamore wrote:

On 29/04/2020 08:10, Peter Levart wrote:
Right, as you saw in a private Email, I did exactly that in a revised version (posted below). The spurious ISE may happen but only when close is called prematurely relative to all child scope close(s) that were or are still active. So we could say the other way: if close was not called prematurely, the ISE on acquire would not be spurious - so ordering of close relative to later acquire was wrong anyway and the exception is an "indication" of that wrong ordering

Unless we want to use close() to "probe" the scope whether it is still active or not, I don't think this should present a problem.

One quick comment: unless I'm missing something, this is starting to make a pretty strong assumption on how acquire()/close() are going to be used. Yes, if acquire() is not exposed to developers (as in the current API) and only hidden behind a spliterator, we might get away with this; but should we at some point re-introduce some kind of explicit acquire mechanism in the API, then such an assumption would not be a fine one to make.

Actually, the more I think of it, the less I'm convinced that, even in the restricted case of acquire() that the API has now, the proposed implementation is correct.

A client has a segment, and it creates a spliterator for it. Then it gives the spliterator to some thread pool which will happily work away with the segment.

But, the client code prematurely closes the segment - this operation should fail with exception, as per javadoc, if there are other actors working on the segment. Your implementation does that, but that failure leaves a sneaky side-effect - in that the threads in the thread-pool might not be able to continue their work on the segment.

Think differently: what if the client succeeded in closing the segment, just because it did it in a time window when no thread in the thread pool held an open scope (this is entirely possible with parallel stream for example since threads periodically acquire and close scopes). This would have the same effect on threads in the thread pool - they would not be able to continue their work... What I'm trying to say is that this is just a mechanism to make things safe, not to coordinate work. If program wants to avoid trouble, it must carefully coordinate work of threads.


This action-at-a-distance between a failed close and a pending acquire is not documented anywhere, and I also find it very counter-intuitive.

So, while I agree there might be ways to have a more scalable scope implementation, I think this is a problem that needs to be addressed.

If we were willing to change the spec a bit, I would then be more inclined to say that when you call MemorySegment::close you always close - period; under no circumstances is an exception thrown. If there are pending acquires on the segment, we keep spinning until there aren't, and then we close for good.

I think that would be a more stable semantics, rather than one where it seems like the operation failed, but in reality, it succeeded in part ;-) (at least for a period of time)

Well, you might not agree, but I don't think of this as a problem. You are trying to define some "correct" behavior to a program that is incorrectly written anyway. I'm just saying that if the program is correctly written, then there is no exceptions. And not defining the behavior for incorrect programs is not that uncommon. Just think of Java memory model. How much of a program behavior is guaranteed when program has data races?

Regards, Peter


Maurizio


Maurizio


Reply via email to