org.codehaus.groovy.util.AbstractConcurrentDoubleKeyMap Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of groovy-all Show documentation
Show all versions of groovy-all Show documentation
Groovy: A powerful, dynamic language for the JVM
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 abstract class AbstractConcurrentDoubleKeyMap extends AbstractConcurrentMapBase {
public AbstractConcurrentDoubleKeyMap(Object segmentInfo) {
super(segmentInfo);
}
static int hash(K1 key1, K2 key2) {
int h = 31*key1.hashCode() + key2.hashCode();
h += ~(h << 9);
h ^= (h >>> 14);
h += (h << 4);
h ^= (h >>> 10);
return h;
}
public V get(K1 key1, K2 key2) {
int hash = hash(key1, key2);
return segmentFor(hash).get(key1, key2, hash);
}
public Entry getOrPut(K1 key1, K2 key2, V value) {
int hash = hash(key1,key2);
return segmentFor(hash).getOrPut(key1, key2, hash, value);
}
public void put(K1 key1, K2 key2, V value) {
int hash = hash(key1, key2);
segmentFor(hash).put(key1, key2, hash).setValue(value);
}
public void remove(K1 key1, K2 key2) {
int hash = hash(key1, key2);
segmentFor(hash).remove(key1, key2, hash);
}
public final Segment segmentFor(int hash) {
return (Segment) segments[(hash >>> segmentShift) & segmentMask];
}
abstract static class Segment extends AbstractConcurrentMapBase.Segment {
Segment(int initialCapacity) {
super(initialCapacity);
}
V get(K1 key1, K2 key2, int hash) {
Object[] tab = table;
Object o = tab[hash & (tab.length - 1)];
if (o != null) {
if (o instanceof Entry) {
Entry e = (Entry) o;
if (e.isEqual(key1,key2,hash)) {
return e.getValue();
}
}
else {
Object arr [] = (Object[]) o;
for (int i = 0; i != arr.length; ++i) {
Entry e = (Entry) arr [i];
if (e != null && e.isEqual(key1, key2, hash))
return e.getValue();
}
}
}
return null;
}
Entry getOrPut(K1 key1, K2 key2, int hash, V value) {
Object[] tab = table;
Object o = tab[hash & (tab.length - 1)];
if (o != null) {
if (o instanceof Entry) {
Entry e = (Entry) o;
if (e.isEqual(key1,key2,hash)) {
return e;
}
}
else {
Object arr [] = (Object[]) o;
for (int i = 0; i != arr.length; ++i) {
Entry e = (Entry) arr [i];
if (e != null && e.isEqual(key1, key2, hash))
return e;
}
}
}
final Entry kvEntry = put(key1, key2, hash);
kvEntry.setValue(value);
return kvEntry;
}
Entry put(K1 key1, K2 key2, int hash) {
lock();
try {
rehashIfThresholdExceeded();
Object[] tab = table;
final int index = hash & (tab.length - 1);
final Object o = tab[index];
if (o != null) {
if (o instanceof Entry) {
final Entry e = (Entry) o;
if (e.isEqual(key1,key2,hash)) {
return e;
}
final Object[] arr = new Object[2];
final Entry res = createEntry(key1, key2, hash);
arr [0] = res;
arr [1] = e;
tab[index] = arr;
count++; // write-volatile
return res;
}
else {
Object arr [] = (Object[]) o;
for (int i = 0; i != arr.length; ++i) {
Entry e = (Entry) arr [i];
if (e != null && e.isEqual(key1, key2, hash)) {
return e;
}
}
final Object[] newArr = new Object[arr.length+1];
final Entry res = createEntry(key1,key2, hash);
arr [0] = res;
System.arraycopy(arr, 0, newArr, 1, arr.length);
tab[index] = arr;
count++; // write-volatile
return res;
}
}
final Entry res = createEntry(key1, key2, hash);
tab[index] = res;
count++; // write-volatile
return res;
} finally {
unlock();
}
}
public void remove(K1 key1, K2 key2, int hash) {
lock();
try {
int c = count-1;
final Object[] tab = table;
final int index = hash & (tab.length - 1);
Object o = tab[index];
if (o != null) {
if (o instanceof Entry) {
if (((Entry)o).isEqual(key1, key2, hash)) {
tab[index] = null;
count = c;
}
}
else {
Object arr [] = (Object[]) o;
for (int i = 0; i < arr.length; i++) {
Entry e = (Entry) arr[i];
if (e != null && e.isEqual(key1, key2, hash)) {
arr [i] = null;
count = c;
break;
}
}
}
}
}
finally {
unlock();
}
}
protected abstract Entry createEntry(K1 key1, K2 key2, int hash);
}
interface Entry extends AbstractConcurrentMapBase.Entry{
boolean isEqual(K1 key1, K2 key2, int hash);
}
}