(@Nullable Object value)
| 4217 | } |
| 4218 | |
| 4219 | @Override |
| 4220 | public boolean containsValue(@Nullable Object value) { |
| 4221 | // does not impact recency ordering |
| 4222 | if (value == null) { |
| 4223 | return false; |
| 4224 | } |
| 4225 | |
| 4226 | // This implementation is patterned after ConcurrentHashMap, but without the locking. The only |
| 4227 | // way for it to return a false negative would be for the target value to jump around in the map |
| 4228 | // such that none of the subsequent iterations observed it, despite the fact that at every point |
| 4229 | // in time it was present somewhere int the map. This becomes increasingly unlikely as |
| 4230 | // CONTAINS_VALUE_RETRIES increases, though without locking it is theoretically possible. |
| 4231 | long now = ticker.read(); |
| 4232 | final Segment<K, V>[] segments = this.segments; |
| 4233 | long last = -1L; |
| 4234 | for (int i = 0; i < CONTAINS_VALUE_RETRIES; i++) { |
| 4235 | long sum = 0L; |
| 4236 | for (Segment<K, V> segment : segments) { |
| 4237 | // ensure visibility of most recent completed write |
| 4238 | int unused = segment.count; // read-volatile |
| 4239 | |
| 4240 | AtomicReferenceArray<ReferenceEntry<K, V>> table = segment.table; |
| 4241 | for (int j = 0; j < table.length(); j++) { |
| 4242 | for (ReferenceEntry<K, V> e = table.get(j); e != null; e = e.getNext()) { |
| 4243 | V v = segment.getLiveValue(e, now); |
| 4244 | if (v != null && valueEquivalence.equivalent(value, v)) { |
| 4245 | return true; |
| 4246 | } |
| 4247 | } |
| 4248 | } |
| 4249 | sum += segment.modCount; |
| 4250 | } |
| 4251 | if (sum == last) { |
| 4252 | break; |
| 4253 | } |
| 4254 | last = sum; |
| 4255 | } |
| 4256 | return false; |
| 4257 | } |
| 4258 | |
| 4259 | @Override |
| 4260 | public V put(K key, V value) { |
nothing calls this directly
no test coverage detected