All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.codehaus.groovy.util.AbstractConcurrentDoubleKeyMap Maven / Gradle / Ivy

There is a newer version: 3.9
Show newest version
/*
 * Copyright 2003-2010 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 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 {
                int c = count;
                if (c++ > threshold) {
                    rehash();
                }

                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 = c; // 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 = c; // write-volatile
                        return res;
                    }
                }

                final Entry res = createEntry(key1, key2, hash);
                tab[index] = res;
                count = c; // 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);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy