From 15a6608842bbe5e71d91f340cf3faca0e3f2fc6f Mon Sep 17 00:00:00 2001 From: Rob Austin Date: Thu, 24 Jul 2014 16:59:53 +0100 Subject: [PATCH] HCOLL-119 removed the use of " public SharedHashMap create(File file, Class kClass, Class vClass) " --- .../openhft/chronicle/map/ChronicleMap.java | 1 - .../collections/ConcurrentHashMap.java | 795 +----------------- .../ConcurrentMapLamdadSupport.java | 4 +- .../net/openhft/collections/KeySetView.java | 89 ++ .../openhft/collections/VanillaSharedMap.java | 613 +++++++++++++- .../chronicle/map/ChronicleMap8Test.java | 9 +- 6 files changed, 688 insertions(+), 823 deletions(-) create mode 100644 src/main/java/net/openhft/collections/KeySetView.java diff --git a/src/main/java/net/openhft/chronicle/map/ChronicleMap.java b/src/main/java/net/openhft/chronicle/map/ChronicleMap.java index 42ae93618..c84bdb22d 100644 --- a/src/main/java/net/openhft/chronicle/map/ChronicleMap.java +++ b/src/main/java/net/openhft/chronicle/map/ChronicleMap.java @@ -106,7 +106,6 @@ public interface ChronicleMap extends SharedHashMap, ConcurrentMapLa */ default void replaceAll(BiFunction function) { Objects.requireNonNull(function); - final BiConsumer action = (k, v) -> { while (!replace(k, v, function.apply(k, v))) { // v changed or k is gone diff --git a/src/main/java/net/openhft/collections/ConcurrentHashMap.java b/src/main/java/net/openhft/collections/ConcurrentHashMap.java index 8cbe16c5c..aa9266b5b 100644 --- a/src/main/java/net/openhft/collections/ConcurrentHashMap.java +++ b/src/main/java/net/openhft/collections/ConcurrentHashMap.java @@ -88,9 +88,9 @@ import java.util.stream.Stream; * same {@code hashCode()} is a sure way to slow down performance of any hash table. To ameliorate impact, * when keys are {@link Comparable}, this class may use comparison order among keys to help break ties. * - *

A {@link Set} projection of a ConcurrentHashMap may be created (using {@link #newKeySet()} or {@link - * #newKeySet(int)}), or viewed (using {@link #keySet(Object)} when only keys are of interest, and the mapped - * values are (perhaps transiently) not used or all take the same mapping value. + *

A {@link Set} projection of a ConcurrentHashMap may be created (using {@link )} or {@link # (int)}), or + * viewed (using {@link # (Object)} when only keys are of interest, and the mapped values are (perhaps + * transiently) not used or all take the same mapping value. * *

A ConcurrentHashMap can be used as scalable frequency map (a form of histogram or multiset) by using * {@link java.util.concurrent.atomic.LongAdder} values and initializing via {@link #computeIfAbsent @@ -183,7 +183,7 @@ import java.util.stream.Stream; * @author Doug Lea * @since 1.5 */ -public class ConcurrentHashMap extends AbstractMap +public abstract class ConcurrentHashMap extends AbstractMap implements ConcurrentMap, Serializable { private static final long serialVersionUID = 7249069246763182397L; @@ -722,10 +722,6 @@ public class ConcurrentHashMap extends AbstractMap */ private transient volatile CounterCell[] counterCells; - // views - private transient KeySetView keySet; - private transient ValuesView values; - private transient EntrySetView entrySet; /* ---------------- Public operations -------------- */ @@ -822,7 +818,6 @@ public class ConcurrentHashMap extends AbstractMap }*/ - /** * Returns the value to which the specified key is mapped, or {@code null} if this map contains no mapping * for the key. @@ -910,7 +905,7 @@ public class ConcurrentHashMap extends AbstractMap /** * Implementation for put and putIfAbsent */ - final V putVal(K key, V value, boolean onlyIfAbsent) { + V putVal(K key, V value, boolean onlyIfAbsent) { if (key == null || value == null) throw new NullPointerException(); int hash = spread(key.hashCode()); int binCount = 0; @@ -1107,64 +1102,6 @@ public class ConcurrentHashMap extends AbstractMap addCount(delta, -1); } - /** - * Returns a {@link Set} view of the keys contained in this map. The set is backed by the map, so changes - * to the map are reflected in the set, and vice-versa. The set supports element removal, which removes - * the corresponding mapping from this map, via the {@code Iterator.remove}, {@code Set.remove}, {@code - * removeAll}, {@code retainAll}, and {@code clear} operations. It does not support the {@code add} or - * {@code addAll} operations. - * - *

The view's iterators and spliterators are weakly - * consistent. - * - *

The view's {@code spliterator} reports {@link Spliterator#CONCURRENT}, {@link Spliterator#DISTINCT}, - * and {@link Spliterator#NONNULL}. - * - * @return the set view - */ - public KeySetView keySet() { - KeySetView ks; - return (ks = keySet) != null ? ks : (keySet = new KeySetView(this, null)); - } - - /** - * Returns a {@link Collection} view of the values contained in this map. The collection is backed by the - * map, so changes to the map are reflected in the collection, and vice-versa. The collection supports - * element removal, which removes the corresponding mapping from this map, via the {@code - * Iterator.remove}, {@code Collection.remove}, {@code removeAll}, {@code retainAll}, and {@code clear} - * operations. It does not support the {@code add} or {@code addAll} operations. - * - *

The view's iterators and spliterators are weakly - * consistent. - * - *

The view's {@code spliterator} reports {@link Spliterator#CONCURRENT} and {@link - * Spliterator#NONNULL}. - * - * @return the collection view - */ - public Collection values() { - ValuesView vs; - return (vs = values) != null ? vs : (values = new ValuesView(this)); - } - - /** - * Returns a {@link Set} view of the mappings contained in this map. The set is backed by the map, so - * changes to the map are reflected in the set, and vice-versa. The set supports element removal, which - * removes the corresponding mapping from the map, via the {@code Iterator.remove}, {@code Set.remove}, - * {@code removeAll}, {@code retainAll}, and {@code clear} operations. - * - *

The view's iterators and spliterators are weakly - * consistent. - * - *

The view's {@code spliterator} reports {@link Spliterator#CONCURRENT}, {@link Spliterator#DISTINCT}, - * and {@link Spliterator#NONNULL}. - * - * @return the set view - */ - public Set> entrySet() { - EntrySetView es; - return (es = entrySet) != null ? es : (entrySet = new EntrySetView(this)); - } /** * Returns the hash code value for this {@link Map}, i.e., the sum of, for each key-value pair in the map, @@ -1471,10 +1408,6 @@ public class ConcurrentHashMap extends AbstractMap } - - - - /** * If the value for the specified key is present, attempts to compute a new mapping given the key and its * current mapped value. The entire method invocation is performed atomically. Some attempted update @@ -1560,226 +1493,6 @@ public class ConcurrentHashMap extends AbstractMap return val; } - /** - * Attempts to compute a mapping for the specified key and its current mapped value (or {@code null} if - * there is no current mapping). The entire method invocation is performed atomically. Some attempted - * update operations on this map by other threads may be blocked while computation is in progress, so the - * computation should be short and simple, and must not attempt to update any other mappings of this Map. - * - * @param key key with which the specified value is to be associated - * @param remappingFunction the function to compute a value - * @return the new value associated with the specified key, or null if none - * @throws NullPointerException if the specified key or remappingFunction is null - * @throws IllegalStateException if the computation detectably attempts a recursive update to this map - * that would otherwise never complete - * @throws RuntimeException or Error if the remappingFunction does so, in which case the mapping is - * unchanged - */ - public V compute(K key, - BiFunction remappingFunction) { - if (key == null || remappingFunction == null) - throw new NullPointerException(); - int h = spread(key.hashCode()); - V val = null; - int delta = 0; - int binCount = 0; - for (Node[] tab = table; ; ) { - Node f; - int n, i, fh; - if (tab == null || (n = tab.length) == 0) - tab = initTable(); - else if ((f = tabAt(tab, i = (n - 1) & h)) == null) { - Node r = new ReservationNode(); - synchronized (r) { - if (casTabAt(tab, i, null, r)) { - binCount = 1; - Node node = null; - try { - if ((val = remappingFunction.apply(key, null)) != null) { - delta = 1; - node = new Node(h, key, val, null); - } - } finally { - setTabAt(tab, i, node); - } - } - } - if (binCount != 0) - break; - } else if ((fh = f.hash) == MOVED) - tab = helpTransfer(tab, f); - else { - synchronized (f) { - if (tabAt(tab, i) == f) { - if (fh >= 0) { - binCount = 1; - for (Node e = f, pred = null; ; ++binCount) { - K ek; - if (e.hash == h && - ((ek = e.key) == key || - (ek != null && key.equals(ek)))) { - val = remappingFunction.apply(key, e.val); - if (val != null) - e.val = val; - else { - delta = -1; - Node en = e.next; - if (pred != null) - pred.next = en; - else - setTabAt(tab, i, en); - } - break; - } - pred = e; - if ((e = e.next) == null) { - val = remappingFunction.apply(key, null); - if (val != null) { - delta = 1; - pred.next = - new Node(h, key, val, null); - } - break; - } - } - } else if (f instanceof TreeBin) { - binCount = 1; - TreeBin t = (TreeBin) f; - TreeNode r, p; - if ((r = t.root) != null) - p = r.findTreeNode(h, key, null); - else - p = null; - V pv = (p == null) ? null : p.val; - val = remappingFunction.apply(key, pv); - if (val != null) { - if (p != null) - p.val = val; - else { - delta = 1; - t.putTreeVal(h, key, val); - } - } else if (p != null) { - delta = -1; - if (t.removeTreeNode(p)) - setTabAt(tab, i, untreeify(t.first)); - } - } - } - } - if (binCount != 0) { - if (binCount >= TREEIFY_THRESHOLD) - treeifyBin(tab, i); - break; - } - } - } - if (delta != 0) - addCount((long) delta, binCount); - return val; - } - - /** - * If the specified key is not already associated with a (non-null) value, associates it with the given - * value. Otherwise, replaces the value with the results of the given remapping function, or removes if - * {@code null}. The entire method invocation is performed atomically. Some attempted update operations - * on this map by other threads may be blocked while computation is in progress, so the computation should - * be short and simple, and must not attempt to update any other mappings of this Map. - * - * @param key key with which the specified value is to be associated - * @param value the value to use if absent - * @param remappingFunction the function to recompute a value if present - * @return the new value associated with the specified key, or null if none - * @throws NullPointerException if the specified key or the remappingFunction is null - * @throws RuntimeException or Error if the remappingFunction does so, in which case the mapping is - * unchanged - */ - public V merge(K key, V value, BiFunction remappingFunction) { - if (key == null || value == null || remappingFunction == null) - throw new NullPointerException(); - int h = spread(key.hashCode()); - V val = null; - int delta = 0; - int binCount = 0; - for (Node[] tab = table; ; ) { - Node f; - int n, i, fh; - if (tab == null || (n = tab.length) == 0) - tab = initTable(); - else if ((f = tabAt(tab, i = (n - 1) & h)) == null) { - if (casTabAt(tab, i, null, new Node(h, key, value, null))) { - delta = 1; - val = value; - break; - } - } else if ((fh = f.hash) == MOVED) - tab = helpTransfer(tab, f); - else { - synchronized (f) { - if (tabAt(tab, i) == f) { - if (fh >= 0) { - binCount = 1; - for (Node e = f, pred = null; ; ++binCount) { - K ek; - if (e.hash == h && - ((ek = e.key) == key || - (ek != null && key.equals(ek)))) { - val = remappingFunction.apply(e.val, value); - if (val != null) - e.val = val; - else { - delta = -1; - Node en = e.next; - if (pred != null) - pred.next = en; - else - setTabAt(tab, i, en); - } - break; - } - pred = e; - if ((e = e.next) == null) { - delta = 1; - val = value; - pred.next = - new Node(h, key, val, null); - break; - } - } - } else if (f instanceof TreeBin) { - binCount = 2; - TreeBin t = (TreeBin) f; - TreeNode r = t.root; - TreeNode p = (r == null) ? null : - r.findTreeNode(h, key, null); - val = (p == null) ? value : - remappingFunction.apply(p.val, value); - if (val != null) { - if (p != null) - p.val = val; - else { - delta = 1; - t.putTreeVal(h, key, val); - } - } else if (p != null) { - delta = -1; - if (t.removeTreeNode(p)) - setTabAt(tab, i, untreeify(t.first)); - } - } - } - } - if (binCount != 0) { - if (binCount >= TREEIFY_THRESHOLD) - treeifyBin(tab, i); - break; - } - } - } - if (delta != 0) - addCount((long) delta, binCount); - return val; - } // Hashtable legacy methods @@ -1837,46 +1550,7 @@ public class ConcurrentHashMap extends AbstractMap return (n < 0L) ? 0L : n; // ignore transient negative values } - /** - * Creates a new {@link Set} backed by a ConcurrentHashMap from the given type to {@code Boolean.TRUE}. - * - * @param the element type of the returned set - * @return the new set - * @since 1.8 - */ - public static KeySetView newKeySet() { - return new KeySetView - (new ConcurrentHashMap(), Boolean.TRUE); - } - /** - * Creates a new {@link Set} backed by a ConcurrentHashMap from the given type to {@code Boolean.TRUE}. - * - * @param initialCapacity The implementation performs internal sizing to accommodate this many elements. - * @param the element type of the returned set - * @return the new set - * @throws IllegalArgumentException if the initial capacity of elements is negative - * @since 1.8 - */ - public static KeySetView newKeySet(int initialCapacity) { - return new KeySetView - (new ConcurrentHashMap(initialCapacity), Boolean.TRUE); - } - - /** - * Returns a {@link Set} view of the keys in this map, using the given common mapped value for any - * additions (i.e., {@link Collection#add} and {@link Collection#addAll(Collection)}). This is of course - * only appropriate if it is acceptable to use the same value for all additions from this view. - * - * @param mappedValue the mapped value to use for any additions - * @return the set view - * @throws NullPointerException if the mappedValue is null - */ - public KeySetView keySet(V mappedValue) { - if (mappedValue == null) - throw new NullPointerException(); - return new KeySetView(this, mappedValue); - } /* ---------------- Special Nodes -------------- */ @@ -3412,464 +3086,6 @@ public class ConcurrentHashMap extends AbstractMap // Parallel bulk operations - - - - - - /* ----------------Views -------------- */ - - /** - * Base class for views. - */ - abstract static class CollectionView - implements Collection, java.io.Serializable { - private static final long serialVersionUID = 7249069246763182397L; - final ConcurrentHashMap map; - - CollectionView(ConcurrentHashMap map) { - this.map = map; - } - - /** - * Returns the map backing this view. - * - * @return the map backing this view - */ - public ConcurrentHashMap getMap() { - return map; - } - - /** - * Removes all of the elements from this view, by removing all the mappings from the map backing this - * view. - */ - public final void clear() { - map.clear(); - } - - public final int size() { - return map.size(); - } - - public final boolean isEmpty() { - return map.isEmpty(); - } - - // implementations below rely on concrete classes supplying these - // abstract methods - - /** - * Returns an iterator over the elements in this collection. - * - *

The returned iterator is weakly consistent. - * - * @return an iterator over the elements in this collection - */ - public abstract Iterator iterator(); - - public abstract boolean contains(Object o); - - public abstract boolean remove(Object o); - - private static final String oomeMsg = "Required array size too large"; - - public final Object[] toArray() { - long sz = map.mappingCount(); - if (sz > MAX_ARRAY_SIZE) - throw new OutOfMemoryError(oomeMsg); - int n = (int) sz; - Object[] r = new Object[n]; - int i = 0; - for (E e : this) { - if (i == n) { - if (n >= MAX_ARRAY_SIZE) - throw new OutOfMemoryError(oomeMsg); - if (n >= MAX_ARRAY_SIZE - (MAX_ARRAY_SIZE >>> 1) - 1) - n = MAX_ARRAY_SIZE; - else - n += (n >>> 1) + 1; - r = Arrays.copyOf(r, n); - } - r[i++] = e; - } - return (i == n) ? r : Arrays.copyOf(r, i); - } - - @SuppressWarnings("unchecked") - public final T[] toArray(T[] a) { - long sz = map.mappingCount(); - if (sz > MAX_ARRAY_SIZE) - throw new OutOfMemoryError(oomeMsg); - int m = (int) sz; - T[] r = (a.length >= m) ? a : - (T[]) java.lang.reflect.Array - .newInstance(a.getClass().getComponentType(), m); - int n = r.length; - int i = 0; - for (E e : this) { - if (i == n) { - if (n >= MAX_ARRAY_SIZE) - throw new OutOfMemoryError(oomeMsg); - if (n >= MAX_ARRAY_SIZE - (MAX_ARRAY_SIZE >>> 1) - 1) - n = MAX_ARRAY_SIZE; - else - n += (n >>> 1) + 1; - r = Arrays.copyOf(r, n); - } - r[i++] = (T) e; - } - if (a == r && i < n) { - r[i] = null; // null-terminate - return r; - } - return (i == n) ? r : Arrays.copyOf(r, i); - } - - /** - * Returns a string representation of this collection. The string representation consists of the - * string representations of the collection's elements in the order they are returned by its iterator, - * enclosed in square brackets ({@code "[]"}). Adjacent elements are separated by the characters - * {@code ", "} (comma and space). Elements are converted to strings as by {@link - * String#valueOf(Object)}. - * - * @return a string representation of this collection - */ - public final String toString() { - StringBuilder sb = new StringBuilder(); - sb.append('['); - Iterator it = iterator(); - if (it.hasNext()) { - for (; ; ) { - Object e = it.next(); - sb.append(e == this ? "(this Collection)" : e); - if (!it.hasNext()) - break; - sb.append(',').append(' '); - } - } - return sb.append(']').toString(); - } - - public final boolean containsAll(Collection c) { - if (c != this) { - for (Object e : c) { - if (e == null || !contains(e)) - return false; - } - } - return true; - } - - public final boolean removeAll(Collection c) { - if (c == null) throw new NullPointerException(); - boolean modified = false; - for (Iterator it = iterator(); it.hasNext(); ) { - if (c.contains(it.next())) { - it.remove(); - modified = true; - } - } - return modified; - } - - public final boolean retainAll(Collection c) { - if (c == null) throw new NullPointerException(); - boolean modified = false; - for (Iterator it = iterator(); it.hasNext(); ) { - if (!c.contains(it.next())) { - it.remove(); - modified = true; - } - } - return modified; - } - - } - - /** - * A view of a ConcurrentHashMap as a {@link Set} of keys, in which additions may optionally be enabled by - * mapping to a common value. This class cannot be directly instantiated. See {@link #keySet() keySet()}, - * {@link #keySet(Object) keySet(V)}, {@link #newKeySet() newKeySet()}, {@link #newKeySet(int) - * newKeySet(int)}. - * - * @since 1.8 - */ - public static class KeySetView extends CollectionView - implements Set, java.io.Serializable { - private static final long serialVersionUID = 7249069246763182397L; - private final V value; - - KeySetView(ConcurrentHashMap map, V value) { // non-public - super(map); - this.value = value; - } - - /** - * Returns the default mapped value for additions, or {@code null} if additions are not supported. - * - * @return the default mapped value for additions, or {@code null} if not supported - */ - public V getMappedValue() { - return value; - } - - /** - * {@inheritDoc} - * - * @throws NullPointerException if the specified key is null - */ - public boolean contains(Object o) { - return map.containsKey(o); - } - - /** - * Removes the key from this map view, by removing the key (and its corresponding value) from the - * backing map. This method does nothing if the key is not in the map. - * - * @param o the key to be removed from the backing map - * @return {@code true} if the backing map contained the specified key - * @throws NullPointerException if the specified key is null - */ - public boolean remove(Object o) { - return map.remove(o) != null; - } - - /** - * @return an iterator over the keys of the backing map - */ - public Iterator iterator() { - Node[] t; - ConcurrentHashMap m = map; - int f = (t = m.table) == null ? 0 : t.length; - return new KeyIterator(t, f, 0, f, m); - } - - /** - * Adds the specified key to this set view by mapping the key to the default mapped value in the - * backing map, if defined. - * - * @param e key to be added - * @return {@code true} if this set changed as a result of the call - * @throws NullPointerException if the specified key is null - * @throws UnsupportedOperationException if no default mapped value for additions was provided - */ - public boolean add(K e) { - V v; - if ((v = value) == null) - throw new UnsupportedOperationException(); - return map.putVal(e, v, true) == null; - } - - /** - * Adds all of the elements in the specified collection to this set, as if by calling {@link #add} on - * each one. - * - * @param c the elements to be inserted into this set - * @return {@code true} if this set changed as a result of the call - * @throws NullPointerException if the collection or any of its elements are {@code null} - * @throws UnsupportedOperationException if no default mapped value for additions was provided - */ - public boolean addAll(Collection c) { - boolean added = false; - V v; - if ((v = value) == null) - throw new UnsupportedOperationException(); - for (K e : c) { - if (map.putVal(e, v, true) == null) - added = true; - } - return added; - } - - public int hashCode() { - int h = 0; - for (K e : this) - h += e.hashCode(); - return h; - } - - public boolean equals(Object o) { - Set c; - return ((o instanceof Set) && - ((c = (Set) o) == this || - (containsAll(c) && c.containsAll(this)))); - } - - public Spliterator spliterator() { - Node[] t; - ConcurrentHashMap m = map; - long n = m.sumCount(); - int f = (t = m.table) == null ? 0 : t.length; - return new KeySpliterator(t, f, 0, f, n < 0L ? 0L : n); - } - - public void forEach(Consumer action) { - if (action == null) throw new NullPointerException(); - Node[] t; - if ((t = map.table) != null) { - Traverser it = new Traverser(t, t.length, 0, t.length); - for (Node p; (p = it.advance()) != null; ) - action.accept(p.key); - } - } - } - - /** - * A view of a ConcurrentHashMap as a {@link Collection} of values, in which additions are disabled. This - * class cannot be directly instantiated. See {@link #values()}. - */ - static final class ValuesView extends CollectionView - implements Collection, java.io.Serializable { - private static final long serialVersionUID = 2249069246763182397L; - - ValuesView(ConcurrentHashMap map) { - super(map); - } - - public final boolean contains(Object o) { - return map.containsValue(o); - } - - public final boolean remove(Object o) { - if (o != null) { - for (Iterator it = iterator(); it.hasNext(); ) { - if (o.equals(it.next())) { - it.remove(); - return true; - } - } - } - return false; - } - - public final Iterator iterator() { - ConcurrentHashMap m = map; - Node[] t; - int f = (t = m.table) == null ? 0 : t.length; - return new ValueIterator(t, f, 0, f, m); - } - - public final boolean add(V e) { - throw new UnsupportedOperationException(); - } - - public final boolean addAll(Collection c) { - throw new UnsupportedOperationException(); - } - - public Spliterator spliterator() { - Node[] t; - ConcurrentHashMap m = map; - long n = m.sumCount(); - int f = (t = m.table) == null ? 0 : t.length; - return new ValueSpliterator(t, f, 0, f, n < 0L ? 0L : n); - } - - public void forEach(Consumer action) { - if (action == null) throw new NullPointerException(); - Node[] t; - if ((t = map.table) != null) { - Traverser it = new Traverser(t, t.length, 0, t.length); - for (Node p; (p = it.advance()) != null; ) - action.accept(p.val); - } - } - } - - /** - * A view of a ConcurrentHashMap as a {@link Set} of (key, value) entries. This class cannot be directly - * instantiated. See {@link #entrySet()}. - */ - static final class EntrySetView extends CollectionView> - implements Set>, java.io.Serializable { - private static final long serialVersionUID = 2249069246763182397L; - - EntrySetView(ConcurrentHashMap map) { - super(map); - } - - public boolean contains(Object o) { - Object k, v, r; - Map.Entry e; - return ((o instanceof Map.Entry) && - (k = (e = (Map.Entry) o).getKey()) != null && - (r = map.get(k)) != null && - (v = e.getValue()) != null && - (v == r || v.equals(r))); - } - - public boolean remove(Object o) { - Object k, v; - Map.Entry e; - return ((o instanceof Map.Entry) && - (k = (e = (Map.Entry) o).getKey()) != null && - (v = e.getValue()) != null && - map.remove(k, v)); - } - - /** - * @return an iterator over the entries of the backing map - */ - public Iterator> iterator() { - ConcurrentHashMap m = map; - Node[] t; - int f = (t = m.table) == null ? 0 : t.length; - return new EntryIterator(t, f, 0, f, m); - } - - public boolean add(Entry e) { - return map.putVal(e.getKey(), e.getValue(), false) == null; - } - - public boolean addAll(Collection> c) { - boolean added = false; - for (Entry e : c) { - if (add(e)) - added = true; - } - return added; - } - - public final int hashCode() { - int h = 0; - Node[] t; - if ((t = map.table) != null) { - Traverser it = new Traverser(t, t.length, 0, t.length); - for (Node p; (p = it.advance()) != null; ) { - h += p.hashCode(); - } - } - return h; - } - - public final boolean equals(Object o) { - Set c; - return ((o instanceof Set) && - ((c = (Set) o) == this || - (containsAll(c) && c.containsAll(this)))); - } - - public Spliterator> spliterator() { - Node[] t; - ConcurrentHashMap m = map; - long n = m.sumCount(); - int f = (t = m.table) == null ? 0 : t.length; - return new EntrySpliterator(t, f, 0, f, n < 0L ? 0L : n, m); - } - - public void forEach(Consumer> action) { - if (action == null) throw new NullPointerException(); - Node[] t; - if ((t = map.table) != null) { - Traverser it = new Traverser(t, t.length, 0, t.length); - for (Node p; (p = it.advance()) != null; ) - action.accept(new MapEntry(p.key, p.val, map)); - } - } - - } - // ------------------------------------------------------- /** @@ -4384,7 +3600,6 @@ public class ConcurrentHashMap extends AbstractMap } - @SuppressWarnings("serial") static final class ReduceKeysTask extends BulkTask { diff --git a/src/main/java/net/openhft/collections/ConcurrentMapLamdadSupport.java b/src/main/java/net/openhft/collections/ConcurrentMapLamdadSupport.java index dd91ddb6a..8567e5023 100644 --- a/src/main/java/net/openhft/collections/ConcurrentMapLamdadSupport.java +++ b/src/main/java/net/openhft/collections/ConcurrentMapLamdadSupport.java @@ -42,12 +42,12 @@ public interface ConcurrentMapLamdadSupport { * * @return the set view */ - public net.openhft.collections.ConcurrentHashMap.KeySetView keySet(); + AbstractVanillaSharedMap.KeySetView keySet(); long mappingCount(); - net.openhft.collections.ConcurrentHashMap.KeySetView keySet(V mappedValue); + net.openhft.collections.KeySetView keySet(V mappedValue); void forEach(long parallelismThreshold, BiConsumer action); diff --git a/src/main/java/net/openhft/collections/KeySetView.java b/src/main/java/net/openhft/collections/KeySetView.java new file mode 100644 index 000000000..74d49bfe9 --- /dev/null +++ b/src/main/java/net/openhft/collections/KeySetView.java @@ -0,0 +1,89 @@ +/* + * Copyright 2014 Higher Frequency Trading + *

+ * http://www.higherfrequencytrading.com + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.openhft.collections; + +import java.util.Collection; +import java.util.Iterator; +import java.util.Set; +import java.util.Spliterator; +import java.util.function.Consumer; + +/** + * @author Rob Austin. + */ +public interface KeySetView extends Collection, java.io.Serializable, Set { + /** + * Returns the default mapped value for additions, or {@code null} if additions are not supported. + * + * @return the default mapped value for additions, or {@code null} if not supported + */ + V getMappedValue(); + + /** + * {@inheritDoc} + * + * @throws NullPointerException if the specified key is null + */ + boolean contains(Object o); + + /** + * Removes the key from this map view, by removing the key (and its corresponding value) from the backing + * map. This method does nothing if the key is not in the map. + * + * @param o the key to be removed from the backing map + * @return {@code true} if the backing map contained the specified key + * @throws NullPointerException if the specified key is null + */ + boolean remove(Object o); + + /** + * @return an iterator over the keys of the backing map + */ + Iterator iterator(); + + /** + * Adds the specified key to this set view by mapping the key to the default mapped value in the backing + * map, if defined. + * + * @param e key to be added + * @return {@code true} if this set changed as a result of the call + * @throws NullPointerException if the specified key is null + * @throws UnsupportedOperationException if no default mapped value for additions was provided + */ + boolean add(K e); + + /** + * Adds all of the elements in the specified collection to this set, as if by calling {@link #add} on each + * one. + * + * @param c the elements to be inserted into this set + * @return {@code true} if this set changed as a result of the call + * @throws NullPointerException if the collection or any of its elements are {@code null} + * @throws UnsupportedOperationException if no default mapped value for additions was provided + */ + boolean addAll(Collection c); + + int hashCode(); + + boolean equals(Object o); + + Spliterator spliterator(); + + void forEach(Consumer action); +} diff --git a/src/main/java/net/openhft/collections/VanillaSharedMap.java b/src/main/java/net/openhft/collections/VanillaSharedMap.java index 0b6342658..4e11623e6 100644 --- a/src/main/java/net/openhft/collections/VanillaSharedMap.java +++ b/src/main/java/net/openhft/collections/VanillaSharedMap.java @@ -28,7 +28,6 @@ import net.openhft.lang.io.serialization.ObjectSerializer; import net.openhft.lang.io.serialization.impl.VanillaBytesMarshallerFactory; import net.openhft.lang.model.Byteable; import net.openhft.lang.model.DataValueClasses; -import net.openhft.lang.model.constraints.NotNull; import net.openhft.lang.model.constraints.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -72,11 +71,542 @@ abstract class AbstractVanillaSharedMap extends net.openhft.collections.Co private SharedHashMapBuilder builder; + // views + + transient ValuesView values; + transient EntrySetView entrySet; + transient KeySetView keySet; + + + /* ----------------Views -------------- */ + + /** + * Base class for views. + */ + abstract static class CollectionView + implements Collection, java.io.Serializable { + private static final long serialVersionUID = 7249069246763182397L; + final AbstractVanillaSharedMap map; + + CollectionView(AbstractVanillaSharedMap map) { + this.map = map; + } + + /** + * Returns the map backing this view. + * + * @return the map backing this view + */ + public AbstractVanillaSharedMap getMap() { + return map; + } + + /** + * Removes all of the elements from this view, by removing all the mappings from the map backing this + * view. + */ + public final void clear() { + map.clear(); + } + + public final int size() { + return map.size(); + } + + public final boolean isEmpty() { + return map.isEmpty(); + } + + // implementations below rely on concrete classes supplying these + // abstract methods + + /** + * Returns an iterator over the elements in this collection. + * + *

The returned iterator is weakly consistent. + * + * @return an iterator over the elements in this collection + */ + public abstract Iterator iterator(); + + public abstract boolean contains(Object o); + + public abstract boolean remove(Object o); + + private static final String oomeMsg = "Required array size too large"; + + public final Object[] toArray() { + long sz = map.mappingCount(); + if (sz > MAX_ARRAY_SIZE) + throw new OutOfMemoryError(oomeMsg); + int n = (int) sz; + Object[] r = new Object[n]; + int i = 0; + for (E e : this) { + if (i == n) { + if (n >= MAX_ARRAY_SIZE) + throw new OutOfMemoryError(oomeMsg); + if (n >= MAX_ARRAY_SIZE - (MAX_ARRAY_SIZE >>> 1) - 1) + n = MAX_ARRAY_SIZE; + else + n += (n >>> 1) + 1; + r = Arrays.copyOf(r, n); + } + r[i++] = e; + } + return (i == n) ? r : Arrays.copyOf(r, i); + } + + @SuppressWarnings("unchecked") + public final T[] toArray(T[] a) { + long sz = map.mappingCount(); + if (sz > MAX_ARRAY_SIZE) + throw new OutOfMemoryError(oomeMsg); + int m = (int) sz; + T[] r = (a.length >= m) ? a : + (T[]) java.lang.reflect.Array + .newInstance(a.getClass().getComponentType(), m); + int n = r.length; + int i = 0; + for (E e : this) { + if (i == n) { + if (n >= MAX_ARRAY_SIZE) + throw new OutOfMemoryError(oomeMsg); + if (n >= MAX_ARRAY_SIZE - (MAX_ARRAY_SIZE >>> 1) - 1) + n = MAX_ARRAY_SIZE; + else + n += (n >>> 1) + 1; + r = Arrays.copyOf(r, n); + } + r[i++] = (T) e; + } + if (a == r && i < n) { + r[i] = null; // null-terminate + return r; + } + return (i == n) ? r : Arrays.copyOf(r, i); + } + + /** + * Returns a string representation of this collection. The string representation consists of the + * string representations of the collection's elements in the order they are returned by its iterator, + * enclosed in square brackets ({@code "[]"}). Adjacent elements are separated by the characters + * {@code ", "} (comma and space). Elements are converted to strings as by {@link + * String#valueOf(Object)}. + * + * @return a string representation of this collection + */ + public final String toString() { + StringBuilder sb = new StringBuilder(); + sb.append('['); + Iterator it = iterator(); + if (it.hasNext()) { + for (; ; ) { + Object e = it.next(); + sb.append(e == this ? "(this Collection)" : e); + if (!it.hasNext()) + break; + sb.append(',').append(' '); + } + } + return sb.append(']').toString(); + } + + public final boolean containsAll(Collection c) { + if (c != this) { + for (Object e : c) { + if (e == null || !contains(e)) + return false; + } + } + return true; + } + + public final boolean removeAll(Collection c) { + if (c == null) throw new NullPointerException(); + boolean modified = false; + for (Iterator it = iterator(); it.hasNext(); ) { + if (c.contains(it.next())) { + it.remove(); + modified = true; + } + } + return modified; + } + + public final boolean retainAll(Collection c) { + if (c == null) throw new NullPointerException(); + boolean modified = false; + for (Iterator it = iterator(); it.hasNext(); ) { + if (!c.contains(it.next())) { + it.remove(); + modified = true; + } + } + return modified; + } + + } + + + /** + * A view of a ConcurrentHashMap as a {@link Collection} of values, in which additions are disabled. This + * class cannot be directly instantiated. See {@link #values()}. + */ + static final class ValuesView extends CollectionView + implements Collection, java.io.Serializable { + private static final long serialVersionUID = 2249069246763182397L; + + ValuesView(AbstractVanillaSharedMap map) { + super(map); + } + + public final boolean contains(Object o) { + return map.containsValue(o); + } + + public final boolean remove(Object o) { + if (o != null) { + for (Iterator it = iterator(); it.hasNext(); ) { + if (o.equals(it.next())) { + it.remove(); + return true; + } + } + } + return false; + } + + public final Iterator iterator() { + ConcurrentHashMap m = map; + Node[] t; + int f = (t = m.table) == null ? 0 : t.length; + return new ValueIterator(t, f, 0, f, m); + } + + public final boolean add(V e) { + throw new UnsupportedOperationException(); + } + + public final boolean addAll(Collection c) { + throw new UnsupportedOperationException(); + } + + public Spliterator spliterator() { + Node[] t; + ConcurrentHashMap m = map; + long n = m.sumCount(); + int f = (t = m.table) == null ? 0 : t.length; + return new ValueSpliterator(t, f, 0, f, n < 0L ? 0L : n); + } + + public void forEach(Consumer action) { + if (action == null) throw new NullPointerException(); + Node[] t; + if ((t = map.table) != null) { + Traverser it = new Traverser(t, t.length, 0, t.length); + for (Node p; (p = it.advance()) != null; ) + action.accept(p.val); + } + } + } + + /** + * A view of a ConcurrentHashMap as a {@link Set} of (key, value) entries. This class cannot be directly + * instantiated. See {@link #entrySet()}. + */ + static final class EntrySetView extends CollectionView> + implements Set>, java.io.Serializable { + private static final long serialVersionUID = 2249069246763182397L; + + EntrySetView(AbstractVanillaSharedMap map) { + super(map); + } + + public boolean contains(Object o) { + Object k, v, r; + Map.Entry e; + return ((o instanceof Map.Entry) && + (k = (e = (Map.Entry) o).getKey()) != null && + (r = map.get(k)) != null && + (v = e.getValue()) != null && + (v == r || v.equals(r))); + } + + public boolean remove(Object o) { + Object k, v; + Map.Entry e; + return ((o instanceof Map.Entry) && + (k = (e = (Map.Entry) o).getKey()) != null && + (v = e.getValue()) != null && + map.remove(k, v)); + } + + /** + * @return an iterator over the entries of the backing map + */ + public Iterator> iterator() { + return new EntryIterator(map); + } + + public boolean add(Entry e) { + return map.putVal(e.getKey(), e.getValue(), false) == null; + } + + public boolean addAll(Collection> c) { + boolean added = false; + for (Entry e : c) { + if (add(e)) + added = true; + } + return added; + } + + public final int hashCode() { + int h = 0; + Node[] t; + if ((t = map.table) != null) { + Traverser it = new Traverser(t, t.length, 0, t.length); + for (Node p; (p = it.advance()) != null; ) { + h += p.hashCode(); + } + } + return h; + } + + public final boolean equals(Object o) { + Set c; + return ((o instanceof Set) && + ((c = (Set) o) == this || + (containsAll(c) && c.containsAll(this)))); + } + + public Spliterator> spliterator() { + Node[] t; + ConcurrentHashMap m = map; + long n = m.sumCount(); + int f = (t = m.table) == null ? 0 : t.length; + return new EntrySpliterator(t, f, 0, f, n < 0L ? 0L : n, m); + } + + public void forEach(Consumer> action) { + if (action == null) throw new NullPointerException(); + Node[] t; + if ((t = map.table) != null) { + Traverser it = new Traverser(t, t.length, 0, t.length); + for (Node p; (p = it.advance()) != null; ) + action.accept(new MapEntry(p.key, p.val, map)); + } + } + + } + + + /** + * Creates a new {@link Set} backed by a ConcurrentHashMap from the given type to {@code Boolean.TRUE}. + * + * @param the element type of the returned set + * @return the new set + * @since 1.8 + */ + public static KeySetView newKeySet() { + final SharedHashMapBuilder builder = SharedHashMapBuilder.of(Integer.class, + String.class); + + try { + final AbstractVanillaSharedMap chronicleMap = (AbstractVanillaSharedMap) builder.clone().vClass(Boolean.class).file(null) + .create(); + return new KeySetView + (chronicleMap, Boolean.TRUE); + } catch (IOException e) { + throw new IllegalStateException(e); + } + + } + + /** + * Creates a new {@link Set} backed by a ConcurrentHashMap from the given type to {@code Boolean.TRUE}. + * + * @param initialCapacity The implementation performs internal sizing to accommodate this many elements. + * @param the element type of the returned set + * @return the new set + * @throws IllegalArgumentException if the initial capacity of elements is negative + * @since 1.8 + */ + public static KeySetView newKeySet(int initialCapacity) { + return newKeySet(); + } + + /** + * Returns a {@link Set} view of the keys in this map, using the given common mapped value for any + * additions (i.e., {@link Collection#add} and {@link Collection#addAll(Collection)}). This is of course + * only appropriate if it is acceptable to use the same value for all additions from this view. + * + * @param mappedValue the mapped value to use for any additions + * @return the set view + * @throws NullPointerException if the mappedValue is null + */ + public KeySetView keySet(V mappedValue) { + if (mappedValue == null) + throw new NullPointerException(); + return new KeySetView(this, mappedValue); + } + + /** + * A view of a ConcurrentHashMap as a {@link Set} of keys, in which additions may optionally be enabled by + * mapping to a common value. This class cannot be directly instantiated. See {@link #keySet() keySet()}, + * {@link #keySet(Object) keySet(V)}, {@link #newKeySet() newKeySet()}, {@link #newKeySet(int) + * newKeySet(int)}. + * + * @since 1.8 + */ + public static class KeySetView extends CollectionView + implements Set, java.io.Serializable, net.openhft.collections.KeySetView { + private static final long serialVersionUID = 7249069246763182397L; + private final V value; + + KeySetView(AbstractVanillaSharedMap map, V value) { // non-public + super(map); + this.value = value; + } + + /** + * Returns the default mapped value for additions, or {@code null} if additions are not supported. + * + * @return the default mapped value for additions, or {@code null} if not supported + */ + public V getMappedValue() { + return value; + } + + /** + * {@inheritDoc} + * + * @throws NullPointerException if the specified key is null + */ + public boolean contains(Object o) { + return map.containsKey(o); + } + + /** + * Removes the key from this map view, by removing the key (and its corresponding value) from the + * backing map. This method does nothing if the key is not in the map. + * + * @param o the key to be removed from the backing map + * @return {@code true} if the backing map contained the specified key + * @throws NullPointerException if the specified key is null + */ + public boolean remove(Object o) { + return map.remove(o) != null; + } + + /** + * @return an iterator over the keys of the backing map + */ + public Iterator iterator() { + Node[] t; + ConcurrentHashMap m = map; + int f = (t = m.table) == null ? 0 : t.length; + return new KeyIterator(t, f, 0, f, m); + } + + /** + * Adds the specified key to this set view by mapping the key to the default mapped value in the + * backing map, if defined. + * + * @param e key to be added + * @return {@code true} if this set changed as a result of the call + * @throws NullPointerException if the specified key is null + * @throws UnsupportedOperationException if no default mapped value for additions was provided + */ + public boolean add(K e) { + V v; + if ((v = value) == null) + throw new UnsupportedOperationException(); + + return map.putVal(e, v, true) == null; + } + + /** + * Adds all of the elements in the specified collection to this set, as if by calling {@link #add} on + * each one. + * + * @param c the elements to be inserted into this set + * @return {@code true} if this set changed as a result of the call + * @throws NullPointerException if the collection or any of its elements are {@code null} + * @throws UnsupportedOperationException if no default mapped value for additions was provided + */ + public boolean addAll(Collection c) { + boolean added = false; + V v; + if ((v = value) == null) + throw new UnsupportedOperationException(); + for (K e : c) { + if (map.putVal(e, v, true) == null) + added = true; + } + return added; + } + + public int hashCode() { + int h = 0; + for (K e : this) + h += e.hashCode(); + return h; + } + + public boolean equals(Object o) { + Set c; + return ((o instanceof Set) && + ((c = (Set) o) == this || + (containsAll(c) && c.containsAll(this)))); + } + + public Spliterator spliterator() { + Node[] t; + ConcurrentHashMap m = map; + long n = m.sumCount(); + int f = (t = m.table) == null ? 0 : t.length; + return new KeySpliterator(t, f, 0, f, n < 0L ? 0L : n); + } + + public void forEach(Consumer action) { + if (action == null) throw new NullPointerException(); + Node[] t; + if ((t = map.table) != null) { + Traverser it = new Traverser(t, t.length, 0, t.length); + for (Node p; (p = it.advance()) != null; ) + action.accept(p.key); + } + } + } + + + /** + * Returns a {@link Set} view of the keys contained in this map. The set is backed by the map, so changes + * to the map are reflected in the set, and vice-versa. The set supports element removal, which removes + * the corresponding mapping from this map, via the {@code Iterator.remove}, {@code Set.remove}, {@code + * removeAll}, {@code retainAll}, and {@code clear} operations. It does not support the {@code add} or + * {@code addAll} operations. + * + *

The view's iterators and spliterators are weakly + * consistent. + * + *

The view's {@code spliterator} reports {@link Spliterator#CONCURRENT}, {@link Spliterator#DISTINCT}, + * and {@link Spliterator#NONNULL}. + * + * @return the set view + */ + public AbstractVanillaSharedMap.KeySetView keySet() { + KeySetView ks; + return (ks = keySet) != null ? ks : (keySet = new KeySetView(this, null)); + } + // todo consider a better way to do this so that is is not creating an entry object each time public void forEach(BiConsumer action) { if (action == null) throw new NullPointerException(); - final EntryIterator entryIterator = new EntryIterator(); + final EntryIterator entryIterator = new EntryIterator(this); for (Entry e = entryIterator.next(); entryIterator.hasNext(); e = entryIterator.next()) { action.accept(e.getKey(), e.getValue()); @@ -887,8 +1417,6 @@ abstract class AbstractVanillaSharedMap extends net.openhft.collections.Co final boolean putReturnsNull; final boolean removeReturnsNull; - transient Set> entrySet; - public AbstractVanillaSharedMap(SharedHashMapBuilder builder, Class kClass, Class vClass) throws IOException { @@ -1099,7 +1627,7 @@ abstract class AbstractVanillaSharedMap extends net.openhft.collections.Co @Override public V put(K key, V value) { super.put(key, value); - return put0(key, value, true); + return putVal(key, value, true); } @@ -1108,10 +1636,11 @@ abstract class AbstractVanillaSharedMap extends net.openhft.collections.Co */ @Override public V putIfAbsent(K key, V value) { - return put0(key, value, false); + return putVal(key, value, false); } - private V put0(K key, V value, boolean replaceIfPresent) { + V putVal(K key, V value, boolean replaceIfPresent) { + super.putVal(key, value, replaceIfPresent); checkKey(key); checkValue(value); Bytes keyBytes = getKeyAsBytes(key); @@ -1170,6 +1699,7 @@ abstract class AbstractVanillaSharedMap extends net.openhft.collections.Co return segments[segmentNum].acquire(keyBytes, key, value, segmentHash, create); } + /** * {@inheritDoc} */ @@ -1190,15 +1720,45 @@ abstract class AbstractVanillaSharedMap extends net.openhft.collections.Co segment.clear(); } + /** - * {@inheritDoc} + * Returns a {@link Collection} view of the values contained in this map. The collection is backed by the + * map, so changes to the map are reflected in the collection, and vice-versa. The collection supports + * element removal, which removes the corresponding mapping from this map, via the {@code + * Iterator.remove}, {@code Collection.remove}, {@code removeAll}, {@code retainAll}, and {@code clear} + * operations. It does not support the {@code add} or {@code addAll} operations. + * + *

The view's iterators and spliterators are weakly + * consistent. + * + *

The view's {@code spliterator} reports {@link Spliterator#CONCURRENT} and {@link + * Spliterator#NONNULL}. + * + * @return the collection view */ - @NotNull - @Override - public Set> entrySet() { - return (entrySet != null) ? entrySet : (entrySet = new EntrySet()); + public Collection values() { + ValuesView vs; + return (vs = values) != null ? vs : (values = new ValuesView(this)); } + /** + * Returns a {@link Set} view of the mappings contained in this map. The set is backed by the map, so + * changes to the map are reflected in the set, and vice-versa. The set supports element removal, which + * removes the corresponding mapping from the map, via the {@code Iterator.remove}, {@code Set.remove}, + * {@code removeAll}, {@code retainAll}, and {@code clear} operations. + * + *

The view's iterators and spliterators are weakly + * consistent. + * + *

The view's {@code spliterator} reports {@link Spliterator#CONCURRENT}, {@link Spliterator#DISTINCT}, + * and {@link Spliterator#NONNULL}. + * + * @return the set view + */ + public Set> entrySet() { + EntrySetView es; + return (es = entrySet) != null ? es : (entrySet = new EntrySetView(this)); + } /** * {@inheritDoc} @@ -2139,16 +2699,19 @@ abstract class AbstractVanillaSharedMap extends net.openhft.collections.Co } } - final class EntryIterator implements Iterator>, IntIntMultiMap.EntryConsumer { + static final class EntryIterator implements Iterator>, IntIntMultiMap.EntryConsumer { - int segmentIndex = segments.length; + private final AbstractVanillaSharedMap map; + private int segmentIndex; Entry nextEntry, lastReturned; Deque segmentPositions = new ArrayDeque(); //todo: replace with a more efficient, auto resizing int[] - EntryIterator() { + EntryIterator(AbstractVanillaSharedMap map) { nextEntry = nextSegmentEntry(); + this.map = map; + segmentIndex = map.segments.length; } public boolean hasNext() { @@ -2157,7 +2720,7 @@ abstract class AbstractVanillaSharedMap extends net.openhft.collections.Co public void remove() { if (lastReturned == null) throw new IllegalStateException(); - AbstractVanillaSharedMap.this.remove(lastReturned.getKey()); + map.remove(lastReturned.getKey()); lastReturned = null; } @@ -2175,17 +2738,17 @@ abstract class AbstractVanillaSharedMap extends net.openhft.collections.Co if (segmentPositions.isEmpty()) { switchToNextSegment(); } else { - final Segment segment = segments[segmentIndex]; - segment.lock(); + + map.segments[segmentIndex].lock(); try { while (!segmentPositions.isEmpty()) { - Entry entry = segment.getEntry(segmentPositions.removeFirst()); + final Entry entry = (Entry) map.segments[segmentIndex].getEntry(segmentPositions.removeFirst()); if (entry != null) { return entry; } } } finally { - segment.unlock(); + map.segments[segmentIndex].unlock(); } } } @@ -2196,12 +2759,12 @@ abstract class AbstractVanillaSharedMap extends net.openhft.collections.Co segmentPositions.clear(); segmentIndex--; if (segmentIndex >= 0) { - final Segment segment = segments[segmentIndex]; - segment.lock(); + + map.segments[segmentIndex].lock(); try { - segments[segmentIndex].visit(this); + map.segments[segmentIndex].visit(this); } finally { - segment.unlock(); + map.segments[segmentIndex].unlock(); } } } @@ -2214,7 +2777,7 @@ abstract class AbstractVanillaSharedMap extends net.openhft.collections.Co final class EntrySet extends AbstractSet> { public Iterator> iterator() { - return new EntryIterator(); + return new EntryIterator(AbstractVanillaSharedMap.this); } public boolean contains(Object o) { diff --git a/src/test/java/net/openhft/chronicle/map/ChronicleMap8Test.java b/src/test/java/net/openhft/chronicle/map/ChronicleMap8Test.java index e273fb5f1..8ec86420c 100644 --- a/src/test/java/net/openhft/chronicle/map/ChronicleMap8Test.java +++ b/src/test/java/net/openhft/chronicle/map/ChronicleMap8Test.java @@ -32,7 +32,6 @@ import org.junit.Test; import java.io.File; import java.io.IOException; import java.util.*; - import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.LongAdder; import java.util.function.*; @@ -63,7 +62,7 @@ public class ChronicleMap8Test extends JSR166TestCase { } - // return new ChronicleMap(5); + // return new ChronicleMap(5); } @@ -87,8 +86,6 @@ public class ChronicleMap8Test extends JSR166TestCase { } - - } /** @@ -393,7 +390,9 @@ public class ChronicleMap8Test extends JSR166TestCase { shouldThrow(); } catch (NullPointerException e) { } - final net.openhft.collections.ConcurrentHashMap.KeySetView set = map.keySet(one); + + final net.openhft.collections.KeySetView set = map.keySet(one); + set.add(one); set.add(six); set.add(seven);