On 16/10/2013 9:26 PM, Paul Sandoz wrote:

On Oct 16, 2013, at 12:28 PM, David Holmes <david.hol...@oracle.com> wrote:

On 16/10/2013 8:03 PM, Paul Sandoz wrote:

On Oct 16, 2013, at 6:41 AM, David Holmes <david.hol...@oracle.com> wrote:

Okay you have incited me to throw in my 2c :) I think the CME issue has been 
raised a number of times in the past (and if the below doesn't agree with what 
I've said in the past Hey! It's a brand new day! ;-) )

But first, Mike the missing spaces are creeping back in "if(xxx)" :)

For Map I don't think looking for external concurrent modification and throwing 
CME is necessary or worthwhile. These are not thread-safe methods. That covers:
- remove, replace

and it implies that putIfAbsent should not check for or throw CME.

For compute* and merge it is possible that the computation function modifies 
the Map - unlikely perhaps but possible - so CME here seems more reasonable. 
(As for forEach, replaceAll etc.)

I fully agree with removing the retry loops in these non-concurrent 
implementations.

That said it makes ConcurrentMap somewhat different to Map as it never throws 
CME even if it was an internal mutation.


HashMap.compute*/merge methods do not throw CME either. I suppose those methods 
could and do so beyond that of only the entry under computation. I think this 
really points to the fact that, for non-traversal, only concrete 
implementations are capable of reliably detecting a CME and therefore it's best 
to leave it up to those implementations should they choose to do so.

Perhaps HashMap's implementations should throw CME?


Perhaps, seems to be going beyond the call of duty. My inclination is not to 
bother. It becomes most relevant with forEach since the consumer will have 
side-effects that might make it easier to unintentionally slip in a 
modification to the map itself.

I think there is a lot to be said for consistency. At present it seems we don't have a clear idea on how these methods should be spec'd or how the implementations should behave.

But the possibility of CME has to be allowed for in the spec of the interfaced 
methods regardless.


Ideally by not say anything :-) otherwise perhaps a variant of the following:

Not saying anything doesn't permit CME to be thrown.

"If a function value passed to an operation of a non-concurrent map modifies the 
contents of that map then the result of that operation is undefined.  An implementation 
may throw {@link ConcurrentModificationException} in such cases and if so that behaviour 
should be documented."

I don't think it is the Java spirit to allow for undefined behaviour. Wouldn't:

@throws CME if the <function> modifies the map and this is detected by the implementation

give the same flexibility while not being so obviously flimsy? I prefer to see exception info on methods as much as practical - with NPE being the obvious exception (no pun intended).

David
-----

Paul.

Reply via email to