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. > 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: "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." Paul.