if (!oldValue.equals(v)) return false; if (n.casValue(v, newValue)) return true;
/** * Replace entry for key only if currently mapped to some value. * Acts as * <pre> * if ((map.containsKey(key)) { * return map.put(key, value); * } else return null; * </pre> * except that the action is performed atomically. * @param key key with which the specified value is associated. * @param value value to be associated with the specified key. * @return previous value associated with specified key, or <tt>null</tt> * if there was no mapping for key. * @throws ClassCastException if the key cannot be compared with the keys * currently in the map. * @throws NullPointerException if the key or value are <tt>null</tt>. */ public V replace(K key, V value) { if (value == null) throw new NullPointerException(); Comparable<K> k = comparable(key); for (;;) { Node<K,V> n = findNode(k); if (n == null) return null; Object v = n.value; if (v != null && n.casValue(v, value)) return (V)v; } }
if (!n.casValue(v, null)) break; if (!n.appendMarker(f) || !b.casNext(n, f))
if (onlyIfAbsent || n.casValue(v, value)) return (V)v; else
continue; if (!n.casValue(v, null)) break; K key = n.key;
/** * Remove first entry; return either its key or a snapshot. * @param keyOnly if true return key, else return SnapshotEntry * (This is a little ugly, but avoids code duplication.) * @return null if empty, first key if keyOnly true, else key,value entry */ Object doRemoveFirst(boolean keyOnly) { for (;;) { Node<K,V> b = head.node; Node<K,V> n = b.next; if (n == null) return null; Node<K,V> f = n.next; if (n != b.next) continue; Object v = n.value; if (v == null) { n.helpDelete(b, f); continue; } if (!n.casValue(v, null)) continue; if (!n.appendMarker(f) || !b.casNext(n, f)) findFirst(); // retry clearIndexToFirst(); K key = n.key; return (keyOnly)? key : new SnapshotEntry<K,V>(key, (V)v); } }