blob: 0a01b70aece5032ff5f76583eea672f115bd268e [file] [log] [blame]
/*
* Copyright 2003-2007 the original author or authors.
*
* 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 org.codehaus.groovy.util;
public class ManagedDoubleKeyMap<K1,K2,V> extends AbstractConcurrentDoubleKeyMap<K1,K2,V> {
public ManagedDoubleKeyMap(ReferenceBundle bundle) {
super(bundle);
}
protected AbstractConcurrentDoubleKeyMap.Segment<K1,K2,V> createSegment(Object segmentInfo, int cap) {
ReferenceBundle bundle = (ReferenceBundle) segmentInfo;
return new Segment<K1,K2,V>(bundle, cap);
}
static class Segment<K1,K2,V> extends AbstractConcurrentDoubleKeyMap.Segment<K1,K2,V>{
private ReferenceBundle bundle;
public Segment(ReferenceBundle bundle, int cap) {
super(cap);
this.bundle = bundle;
}
protected AbstractConcurrentDoubleKeyMap.Entry<K1,K2,V> createEntry(K1 key1, K2 key2, int hash) {
return new EntryWithValue(bundle, key1, key2, hash, this);
}
}
static class Ref<K> extends ManagedReference<K> {
final Entry entry;
public Ref(ReferenceBundle bundle, K referent, Entry entry) {
super(bundle, referent);
this.entry = entry;
}
public void finalizeRef() {
this.entry.clean();
}
}
public static class Entry<K1,K2, V> implements AbstractConcurrentDoubleKeyMap.Entry<K1,K2,V> {
private final int hash;
final Ref<K1> ref1;
final Ref<K2> ref2;
final Segment segment;
public Entry(ReferenceBundle bundle, K1 key1, K2 key2, int hash, Segment segment) {
this.hash = hash;
this.segment = segment;
ref1 = new Ref(bundle, key1, this);
ref2 = new Ref(bundle, key2, this);
}
public boolean isValid() {
return ref1.get() != null && ref2.get () != null;
}
public boolean isEqual(K1 key1, K2 key2, int hash) {
return this.hash == hash && ref1.get() == key1 && ref2.get() == key2;
}
public V getValue() {
return (V)this;
}
public void setValue(V value) {
}
public int getHash() {
return hash;
}
public void clean() {
segment.removeEntry(this);
ref1.clear();
ref2.clear();
}
}
private static class EntryWithValue<K1,K2,V> extends Entry<K1,K2,V> {
private V value;
public EntryWithValue(ReferenceBundle bundle, K1 key1, K2 key2, int hash, Segment segment) {
super(bundle, key1, key2, hash, segment);
}
public V getValue() {
return value;
}
public void setValue(V value) {
this.value = value;
}
public void clean() {
super.clean();
value = null;
}
}
}