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

org.codehaus.groovy.reflection.WeakDoubleKeyHashMap Maven / Gradle / Ivy

There is a newer version: 1.5.8
Show newest version
/*
 * 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.reflection;

import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;

public class WeakDoubleKeyHashMap extends ComplexKeyHashMap
{
  private static class Ref extends WeakReference {
      public Ref(Object referent, ReferenceQueue q, Entry entry) {
          super(referent, q);
          this.entry = entry;
      }

      Entry entry;
  }

  public static class Entry extends ComplexKeyHashMap.Entry{
    public Ref key1, key2;
  }

  private final ReferenceQueue queue = new ReferenceQueue();

    private void expungeStaleEntries() {
	    Ref r;
        while ( (r = (Ref) queue.poll()) != null) {
            Entry e = r.entry;
            if (e == null)
              continue;

            r.entry = null;
            e.key1 = e.key2 = null;

            int h = e.hash;
            int i = h & (table.length-1);

            Entry prev = (Entry) table[i];
            Entry p = prev;
            while (p != null) {
                Entry next = (Entry) p.next;
                if (p == e) {
                    if (prev == e)
                        table[i] = next;
                    else
                        prev.next = next;
                    e.next = null;  // Help GC
                    e.value = null; //  "   "
                    size--;
                    break;
                }
                prev = p;
                p = next;
            }
        }
    }

  public final Object get(Object key1, Object key2) {
//    expungeStaleEntries();
    int h = hash (31*key1.hashCode()+key2.hashCode());
    ComplexKeyHashMap.Entry e = table [h & (table.length-1)];
    for (; e != null; e = e.next)
      if (e.hash == h && checkEquals((Entry) e, key1, key2))
        return e;

    return null;
  }

    public boolean checkEquals(ComplexKeyHashMap.Entry e, Object key1, Object key2) {
        Entry ee = (Entry) e;
        return ee.key1.get() == key1 && ee.key2.get() == key2;
    }

  public Entry getOrPut(Object key1, Object key2)
  {
//    expungeStaleEntries();
    int h = hash (31*key1.hashCode()+key2.hashCode());
    final int index = h & (table.length - 1);
    ComplexKeyHashMap.Entry e = table [index];
    for (; e != null; e = e.next)
      if (e.hash == h && checkEquals( e, key1, key2))
        return (Entry) e;

    ComplexKeyHashMap.Entry entry = createEntry(key1, key2, h, index);
    table [index] = entry;

    if ( ++size == threshold )
      resize(2*table.length);

    return (Entry) entry;
  }

  private ComplexKeyHashMap.Entry createEntry(Object key1, Object key2, int h, int index)
  {
    Entry entry = createEntry ();
    entry.next = table [index];
    entry.hash = h;
    entry.key1 = new Ref(key1, queue, entry);
    entry.key2 = new Ref(key2, queue, entry);
    return entry;
  }

  public Entry createEntry() {
      return new Entry ();
  }

    public int size() {
        expungeStaleEntries();
        return super.size();
    }

    public final ComplexKeyHashMap.Entry remove(Object key1, Object key2) {
    expungeStaleEntries();
    int h = hash (31*key1.hashCode()+key2.hashCode());
    int index = h & (table.length -1);
    for (ComplexKeyHashMap.Entry e = table [index], prev = null; e != null; prev = e, e = e.next ) {
      if (e.hash == h && checkEquals((Entry) e, key1, key2)) {
        if (prev == null)
          table [index] = e.next;
        else
          prev.next = e.next;
        size--;

        e.next = null;
        return e;
      }
    }

    return null;
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy