Mercurial > hg > graal-compiler
changeset 18379:601dfbdcc5bf
added LinkedIdentityHashMap
author | Doug Simon <doug.simon@oracle.com> |
---|---|
date | Sat, 15 Nov 2014 14:46:39 +0100 |
parents | 3aaf2747961c |
children | 53bd20792127 |
files | graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/remote/LinkedIdentityHashMap.java |
diffstat | 1 files changed, 251 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/remote/LinkedIdentityHashMap.java Sat Nov 15 14:46:39 2014 +0100 @@ -0,0 +1,251 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.common.remote; + +import java.util.*; +import java.util.function.*; + +import com.oracle.graal.compiler.common.remote.Context.Mode; + +/** + * A map that combines {@link IdentityHashMap} with {@link LinkedHashMap} for the purpose of + * ensuring a deterministic execution order during {@link Mode#Capturing}. + */ +final class LinkedIdentityHashMap<K, V> implements Map<K, V> { + + private final LinkedHashMap<Id<K>, V> map; + + public LinkedIdentityHashMap() { + map = new LinkedHashMap<>(); + } + + public LinkedIdentityHashMap(Map<K, V> m) { + map = new LinkedHashMap<>(m.size()); + putAll(m); + } + + public LinkedIdentityHashMap(int expectedMaxSize) { + map = new LinkedHashMap<>(expectedMaxSize); + } + + /** + * Wrapper for an object that gives uses the object's identity for the purpose of equality + * comparisons and computing a hash code. + */ + public static class Id<T> { + final T object; + + public Id(T object) { + assert object != null; + this.object = object; + } + + @SuppressWarnings("unchecked") + @Override + public boolean equals(Object obj) { + return ((Id<T>) obj).object == object; + } + + @Override + public int hashCode() { + return System.identityHashCode(object); + } + } + + public int size() { + return map.size(); + } + + public boolean isEmpty() { + return map.isEmpty(); + } + + public boolean containsKey(Object key) { + return map.containsKey(id(key)); + } + + @SuppressWarnings("unchecked") + private Id<K> id(Object key) { + if (key == null) { + return null; + } + return new Id<>((K) key); + } + + public boolean containsValue(Object value) { + return map.containsValue(value); + } + + public V get(Object key) { + return map.get(id(key)); + } + + public V put(K key, V value) { + return map.put(id(key), value); + } + + public V remove(Object key) { + return map.remove(id(key)); + } + + @SuppressWarnings("unchecked") + public void putAll(Map<? extends K, ? extends V> m) { + if (m != null && m.getClass() == getClass()) { + LinkedIdentityHashMap<K, V> that = (LinkedIdentityHashMap<K, V>) m; + map.putAll(that.map); + + } else { + for (K key : m.keySet()) { + map.put(id(key), m.get(key)); + } + } + } + + public void clear() { + map.clear(); + } + + final class KeySet extends AbstractSet<K> { + @Override + public int size() { + return map.size(); + } + + @Override + public void clear() { + map.clear(); + } + + @Override + public Iterator<K> iterator() { + return new Iterator<K>() { + final Iterator<Id<K>> i = map.keySet().iterator(); + + public boolean hasNext() { + return i.hasNext(); + } + + public K next() { + return i.next().object; + } + + public void remove() { + i.remove(); + } + }; + } + + @Override + public boolean contains(Object o) { + return containsKey(o); + } + + @Override + public boolean remove(Object o) { + return LinkedIdentityHashMap.this.remove(o) != null; + } + + public Spliterator<K> spliterator() { + return Spliterators.spliterator(this, Spliterator.SIZED | Spliterator.ORDERED | Spliterator.DISTINCT); + } + + public void forEach(Consumer<? super K> action) { + throw new UnsupportedOperationException(); + } + } + + public Set<K> keySet() { + return new KeySet(); + } + + public Collection<V> values() { + return map.values(); + } + + final class EntrySet extends AbstractSet<Map.Entry<K, V>> { + @Override + public int size() { + return map.size(); + } + + @Override + public void clear() { + map.clear(); + } + + @Override + public Iterator<Map.Entry<K, V>> iterator() { + return new Iterator<Map.Entry<K, V>>() { + final Iterator<Map.Entry<Id<K>, V>> i = map.entrySet().iterator(); + + public boolean hasNext() { + return i.hasNext(); + } + + public Map.Entry<K, V> next() { + Map.Entry<Id<K>, V> e = i.next(); + return new Map.Entry<K, V>() { + + public K getKey() { + return e.getKey().object; + } + + public V getValue() { + return e.getValue(); + } + + public V setValue(V value) { + return e.setValue(value); + } + }; + } + + public void remove() { + i.remove(); + } + }; + } + + @Override + public boolean contains(Object o) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean remove(Object o) { + throw new UnsupportedOperationException(); + } + + public Spliterator<Map.Entry<K, V>> spliterator() { + throw new UnsupportedOperationException(); + } + + public void forEach(Consumer<? super Map.Entry<K, V>> action) { + throw new UnsupportedOperationException(); + } + } + + public Set<Map.Entry<K, V>> entrySet() { + return new EntrySet(); + } +}