Save This Page
Home » jdo2-util-2.3-ea-src » org.apache.jdo.util » [javadoc | source]
    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements.  See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache License, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * the License.  You may obtain a copy of the License at
    8    * 
    9    *     http://www.apache.org/licenses/LICENSE-2.0
   10    * 
   11    * Unless required by applicable law or agreed to in writing, software 
   12    * distributed under the License is distributed on an "AS IS" BASIS, 
   13    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
   14    * See the License for the specific language governing permissions and 
   15    * limitations under the License.
   16    */
   17   
   18   package org.apache.jdo.util;
   19   
   20   import java.lang.ref.ReferenceQueue;
   21   import java.lang.ref.WeakReference;
   22   import java.util.HashSet;
   23   import java.util.Iterator;
   24   
   25   /**
   26    * A weak HashSet. An element stored in the WeakHashSet might be
   27    * garbage collected, if there is no strong reference to this element.
   28    */
   29   
   30   public class WeakHashSet extends HashSet {
   31       /**
   32        * Helps to detect garbage collected values.
   33        */
   34       ReferenceQueue queue = new ReferenceQueue();
   35   
   36       /**
   37        * Returns an iterator over the elements in this set.  The elements
   38        * are returned in no particular order.
   39        *
   40        * @return an Iterator over the elements in this set.
   41        */
   42       public Iterator iterator() {
   43           // remove garbage collected elements
   44           processQueue();
   45   
   46           // get an iterator of the superclass WeakHashSet
   47           final Iterator i = super.iterator();
   48   
   49           return new Iterator() {
   50               public boolean hasNext() {
   51                   return i.hasNext();
   52               }
   53   
   54               public Object next() {
   55                   // unwrap the element
   56                   return getReferenceObject((WeakReference) i.next());
   57               }
   58   
   59               public void remove() {
   60                   // remove the element from the HashSet
   61                   i.remove();
   62               }
   63           };
   64       }
   65   
   66       /**
   67        * Returns <code>true</code> if this set contains the specified element.
   68        *
   69        * @param o element whose presence in this set is to be tested.
   70        * @return <code>true</code> if this set contains the specified element.
   71        */
   72       public boolean contains(Object o) {
   73           return super.contains(WeakElement.create(o));
   74       }
   75   
   76       /**
   77        * Adds the specified element to this set if it is not already
   78        * present.
   79        *
   80        * @param o element to be added to this set.
   81        * @return <code>true</code> if the set did not already contain the specified
   82        * element.
   83        */
   84       public boolean add(Object o) {
   85           processQueue();
   86           return super.add(WeakElement.create(o, this.queue));
   87       }
   88   
   89       /**
   90        * Removes the given element from this set if it is present.
   91        *
   92        * @param o object to be removed from this set, if present.
   93        * @return <code>true</code> if the set contained the specified element.
   94        */
   95       public boolean remove(Object o) {
   96           boolean ret = super.remove(WeakElement.create(o));
   97           processQueue();
   98           return ret;
   99       }
  100   
  101       /**
  102        * A convenience method to return the object held by the
  103        * weak reference or <code>null</code> if it does not exist.
  104        */
  105       private final Object getReferenceObject(WeakReference ref) {
  106           return (ref == null) ? null : ref.get();
  107       }
  108   
  109       /**
  110        * Removes all garbage collected values with their keys from the map.
  111        * Since we don't know how much the ReferenceQueue.poll() operation
  112        * costs, we should call it only in the add() method.
  113        */
  114       private final void processQueue() {
  115           WeakElement wv = null;
  116   
  117           while ((wv = (WeakElement) this.queue.poll()) != null) {
  118               super.remove(wv);
  119           }
  120       }
  121   
  122       /**
  123        * A WeakHashSet stores objects of class WeakElement.
  124        * A WeakElement wraps the element that should be stored in the WeakHashSet.
  125        * WeakElement inherits from java.lang.ref.WeakReference.
  126        * It redefines equals and hashCode which delegate to the corresponding methods
  127        * of the wrapped element.
  128        */
  129       static private class WeakElement extends WeakReference {
  130           private int hash;	/* Hashcode of key, stored here since the key
  131                                  may be tossed by the GC */
  132   
  133           private WeakElement(Object o) {
  134               super(o);
  135               hash = o.hashCode();
  136           }
  137   
  138           private WeakElement(Object o, ReferenceQueue q) {
  139               super(o, q);
  140               hash = o.hashCode();
  141           }
  142   
  143           private static WeakElement create(Object o) {
  144               return (o == null) ? null : new WeakElement(o);
  145           }
  146   
  147           private static WeakElement create(Object o, ReferenceQueue q) {
  148               return (o == null) ? null : new WeakElement(o, q);
  149           }
  150   
  151           /* A WeakElement is equal to another WeakElement iff they both refer to objects
  152                  that are, in turn, equal according to their own equals methods */
  153           public boolean equals(Object o) {
  154               if (this == o)
  155                   return true;
  156               if (!(o instanceof WeakElement))
  157                   return false;
  158               Object t = this.get();
  159               Object u = ((WeakElement) o).get();
  160               if (t == u) 
  161                   return true;
  162               if ((t == null) || (u == null))
  163                   return false;
  164               return t.equals(u);
  165           }
  166   
  167           public int hashCode() {
  168               return hash;
  169           }
  170       }
  171   
  172   }
  173   
  174   

Save This Page
Home » jdo2-util-2.3-ea-src » org.apache.jdo.util » [javadoc | source]