303 |
|
transient int count; |
304 |
|
|
305 |
|
/** |
306 |
< |
* The total number of insertions and removals in this |
307 |
< |
* segment. Even though this may overflows 32 bits, it |
308 |
< |
* provides sufficient accuracy for stability checks in CHM |
309 |
< |
* isEmpty() and size() methods. Accessed only either within |
310 |
< |
* locks or among other volatile reads that maintain |
311 |
< |
* visibility. |
306 |
> |
* The total number of mutative operations in this segment. |
307 |
> |
* Even though this may overflows 32 bits, it provides |
308 |
> |
* sufficient accuracy for stability checks in CHM isEmpty() |
309 |
> |
* and size() methods. Accessed only either within locks or |
310 |
> |
* among other volatile reads that maintain visibility. |
311 |
|
*/ |
312 |
|
transient int modCount; |
313 |
|
|
346 |
|
if ((k = e.key) == key || |
347 |
|
(e.hash == hash && key.equals(k))) { |
348 |
|
oldValue = e.value; |
349 |
< |
if (!onlyIfAbsent) |
349 |
> |
if (!onlyIfAbsent) { |
350 |
|
e.value = value; |
351 |
+ |
++modCount; |
352 |
+ |
} |
353 |
|
break; |
354 |
|
} |
355 |
|
e = e.next; |
446 |
|
/** |
447 |
|
* Scans for a node containing given key while trying to |
448 |
|
* acquire lock, creating and returning one if not found. Upon |
449 |
< |
* return, guarantees that lock is held. |
449 |
> |
* return, guarantees that lock is held. UNlike in most |
450 |
> |
* methods, calls to method equals are not screened: Since |
451 |
> |
* traversal speed doesn't matter, we might as well help warm |
452 |
> |
* up the associated code and accesses as well. |
453 |
|
* |
454 |
|
* @return a new node if key not found, else null |
455 |
|
*/ |
566 |
|
(e.hash == hash && key.equals(k))) { |
567 |
|
if (oldValue.equals(e.value)) { |
568 |
|
e.value = newValue; |
569 |
+ |
++modCount; |
570 |
|
replaced = true; |
571 |
|
} |
572 |
|
break; |
590 |
|
(e.hash == hash && key.equals(k))) { |
591 |
|
oldValue = e.value; |
592 |
|
e.value = value; |
593 |
+ |
++modCount; |
594 |
|
break; |
595 |
|
} |
596 |
|
} |
926 |
|
* @throws NullPointerException if the specified value is null |
927 |
|
*/ |
928 |
|
public boolean containsValue(Object value) { |
929 |
< |
// Same idea as size() but using hashes as checksum |
929 |
> |
// Same idea as size() |
930 |
|
if (value == null) |
931 |
|
throw new NullPointerException(); |
932 |
|
final Segment<K,V>[] segments = this.segments; |
933 |
|
boolean found = false; |
934 |
< |
long last = 0L; |
934 |
> |
long last = 0; |
935 |
|
int retries = -1; |
936 |
|
try { |
937 |
|
outer: for (;;) { |
939 |
|
for (int j = 0; j < segments.length; ++j) |
940 |
|
ensureSegment(j).lock(); // force creation |
941 |
|
} |
942 |
< |
long sum = 0L; |
942 |
> |
long hashSum = 0L; |
943 |
> |
int sum = 0; |
944 |
|
for (int j = 0; j < segments.length; ++j) { |
945 |
|
HashEntry<K,V>[] tab; |
946 |
|
Segment<K,V> seg = segmentAt(segments, j); |
953 |
|
found = true; |
954 |
|
break outer; |
955 |
|
} |
949 |
– |
sum += e.hash; |
956 |
|
} |
957 |
|
} |
958 |
+ |
sum += seg.modCount; |
959 |
|
} |
960 |
|
} |
961 |
|
if (retries > 0 && sum == last) |