soot.jimple.infoflow.collect.ConcurrentIdentityHashMultiMap Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of soot-infoflow Show documentation
Show all versions of soot-infoflow Show documentation
Soot extending data flow tracking components for Java
/* Soot - a J*va Optimization Framework
* Copyright (C) 2002 Ondrej Lhotak
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
package soot.jimple.infoflow.collect;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import soot.util.AbstractMultiMap;
import soot.util.HashMultiMap;
import soot.util.MultiMap;
/**
* A concurrent version of the {@link HashMultiMap} that uses object identity
* for comparison
*
* @author Steven Arzt
*
*/
public class ConcurrentIdentityHashMultiMap extends AbstractMultiMap {
private static final long serialVersionUID = -6721251660349964507L;
Map> m = new ConcurrentIdentityHashMap>();
public ConcurrentIdentityHashMultiMap() {}
public ConcurrentIdentityHashMultiMap( MultiMap m ) {
putAll( m );
}
@Override
public int numKeys() {
return m.size();
}
@Override
public boolean containsKey( Object key ) {
return m.containsKey( key );
}
@Override
public boolean containsValue( V value ) {
for (Map s: m.values())
if (s.containsKey(value)) return true;
return false;
}
protected ConcurrentMap newSet() {
return new ConcurrentHashMap();
}
private ConcurrentMap findSet( K key ) {
ConcurrentMap s = m.get( key );
if( s == null ) {
synchronized (this) {
// Better check twice, another thread may have created a set in
// the meantime
s = m.get( key );
if( s == null ) {
s = newSet();
m.put( key, s );
}
}
}
return s;
}
@Override
public boolean put( K key, V value ) {
return findSet( key ).put( value, value ) == null;
}
public V putIfAbsent( K key, V value ) {
return findSet( key ).putIfAbsent( value, value );
}
@Override
public boolean putAll( K key, Set values ) {
if (values.isEmpty()) return false;
Map set = findSet( key );
boolean ok = false;
for (V v : values)
if (set.put(v, v) == null)
ok = true;
return ok;
}
@Override
public boolean remove( K key, V value ) {
Map s = m.get( key );
if( s == null ) return false;
boolean ret = s.remove( value ) != null;
if( s.isEmpty() ) {
m.remove( key );
}
return ret;
}
@Override
public boolean remove( K key ) {
return null != m.remove( key );
}
@Override
public boolean removeAll( K key, Set values ) {
Map s = m.get( key );
if( s == null ) return false;
boolean ret = false;
for (V v : values)
if (s.remove( v ) != null)
ret = true;
if( s.isEmpty() ) {
m.remove( key );
}
return ret;
}
@Override
public Set get( K o ) {
Map ret = m.get( o );
if( ret == null ) return Collections.emptySet();
return Collections.unmodifiableSet(ret.keySet());
}
@Override
public Set keySet() {
return m.keySet();
}
@Override
public Set values() {
Set ret = new HashSet(m.size());
for (Map s : m.values())
ret.addAll(s.keySet());
return ret;
}
@Override
public boolean equals( Object o ) {
if( ! (o instanceof MultiMap) ) return false;
@SuppressWarnings("unchecked")
MultiMap mm = (MultiMap) o;
if( !keySet().equals( mm.keySet() ) ) return false;
for (Map.Entry> e : m.entrySet()) {
Map s = e.getValue();
if( !s.equals( mm.get( e.getKey() ) ) ) return false;
}
return true;
}
@Override
public int hashCode() {
return m.hashCode();
}
@Override
public int size() {
return m.size();
}
@Override
public void clear() {
m.clear();
}
}