151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/* 251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Copyright (c) 1998, 2006, Oracle and/or its affiliates. All rights reserved. 351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is free software; you can redistribute it and/or modify it 651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * under the terms of the GNU General Public License version 2 only, as 751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * published by the Free Software Foundation. Oracle designates this 851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * particular file as subject to the "Classpath" exception as provided 951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * by Oracle in the LICENSE file that accompanied this code. 1051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 1151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is distributed in the hope that it will be useful, but WITHOUT 1251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * version 2 for more details (a copy is included in the LICENSE file that 1551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * accompanied this code). 1651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 1751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * You should have received a copy of the GNU General Public License version 1851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 2 along with this work; if not, write to the Free Software Foundation, 1951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 2151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * or visit www.oracle.com if you need additional information or have any 2351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * questions. 2451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 2551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 2651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipackage sun.misc; 2751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 2851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.lang.ref.SoftReference; 2951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.lang.ref.ReferenceQueue; 3051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 3151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.Iterator; 3251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.Map; 3351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.AbstractMap; 3451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.HashMap; 3551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.Set; 3651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.AbstractSet; 3751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.NoSuchElementException; 3851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 3951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 4051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/** 4151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * A memory-sensitive implementation of the <code>Map</code> interface. 4251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 4351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p> A <code>SoftCache</code> object uses {@link java.lang.ref.SoftReference 4451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * soft references} to implement a memory-sensitive hash map. If the garbage 4551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * collector determines at a certain point in time that a value object in a 4651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>SoftCache</code> entry is no longer strongly reachable, then it may 4751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * remove that entry in order to release the memory occupied by the value 4851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * object. All <code>SoftCache</code> objects are guaranteed to be completely 4951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * cleared before the virtual machine will throw an 5051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>OutOfMemoryError</code>. Because of this automatic clearing feature, 5151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the behavior of this class is somewhat different from that of other 5251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>Map</code> implementations. 5351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 5451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p> Both null values and the null key are supported. This class has the 5551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * same performance characteristics as the <code>HashMap</code> class, and has 5651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the same efficiency parameters of <em>initial capacity</em> and <em>load 5751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * factor</em>. 5851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 5951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p> Like most collection classes, this class is not synchronized. A 6051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * synchronized <code>SoftCache</code> may be constructed using the 6151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>Collections.synchronizedMap</code> method. 6251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 6351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p> In typical usage this class will be subclassed and the <code>fill</code> 6451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * method will be overridden. When the <code>get</code> method is invoked on a 6551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * key for which there is no mapping in the cache, it will in turn invoke the 6651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>fill</code> method on that key in an attempt to construct a 6751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * corresponding value. If the <code>fill</code> method returns such a value 6851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * then the cache will be updated and the new value will be returned. Thus, 6951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * for example, a simple URL-content cache can be constructed as follows: 7051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 7151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <pre> 7251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * public class URLCache extends SoftCache { 7351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * protected Object fill(Object key) { 7451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * return ((URL)key).getContent(); 7551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * } 7651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * } 7751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * </pre> 7851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 7951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p> The behavior of the <code>SoftCache</code> class depends in part upon 8051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the actions of the garbage collector, so several familiar (though not 8151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * required) <code>Map</code> invariants do not hold for this class. <p> 8251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Because entries are removed from a <code>SoftCache</code> in response to 8351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * dynamic advice from the garbage collector, a <code>SoftCache</code> may 8451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * behave as though an unknown thread is silently removing entries. In 8551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * particular, even if you synchronize on a <code>SoftCache</code> instance and 8651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * invoke none of its mutator methods, it is possible for the <code>size</code> 8751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * method to return smaller values over time, for the <code>isEmpty</code> 8851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * method to return <code>false</code> and then <code>true</code>, for the 8951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>containsKey</code> method to return <code>true</code> and later 9051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>false</code> for a given key, for the <code>get</code> method to 9151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * return a value for a given key but later return <code>null</code>, for the 9251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>put</code> method to return <code>null</code> and the 9351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>remove</code> method to return <code>false</code> for a key that 9451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * previously appeared to be in the map, and for successive examinations of the 9551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * key set, the value set, and the entry set to yield successively smaller 9651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * numbers of elements. 9751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 9851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @author Mark Reinhold 9951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @since 1.2 10051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see java.util.HashMap 10151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see java.lang.ref.SoftReference 10251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 10351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 10451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 10551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipublic class SoftCache extends AbstractMap implements Map { 10651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 10751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* The basic idea of this implementation is to maintain an internal HashMap 10851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski that maps keys to soft references whose referents are the keys' values; 10951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski the various accessor methods dereference these soft references before 11051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski returning values. Because we don't have access to the innards of the 11151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski HashMap, each soft reference must contain the key that maps to it so 11251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski that the processQueue method can remove keys whose values have been 11351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski discarded. Thus the HashMap actually maps keys to instances of the 11451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ValueCell class, which is a simple extension of the SoftReference class. 11551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 11651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 11751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 11851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski static private class ValueCell extends SoftReference { 11951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski static private Object INVALID_KEY = new Object(); 12051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski static private int dropped = 0; 12151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private Object key; 12251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 12351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private ValueCell(Object key, Object value, ReferenceQueue queue) { 12451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski super(value, queue); 12551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski this.key = key; 12651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 12751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 12851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static ValueCell create(Object key, Object value, 12951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ReferenceQueue queue) 13051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski { 13151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (value == null) return null; 13251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return new ValueCell(key, value, queue); 13351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 13451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 13551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static Object strip(Object val, boolean drop) { 13651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (val == null) return null; 13751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ValueCell vc = (ValueCell)val; 13851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Object o = vc.get(); 13951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (drop) vc.drop(); 14051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return o; 14151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 14251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 14351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private boolean isValid() { 14451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return (key != INVALID_KEY); 14551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 14651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 14751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private void drop() { 14851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski super.clear(); 14951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski key = INVALID_KEY; 15051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski dropped++; 15151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 15251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 15351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 15451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 15551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 15651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* Hash table mapping keys to ValueCells */ 15751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private Map hash; 15851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 15951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* Reference queue for cleared ValueCells */ 16051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private ReferenceQueue queue = new ReferenceQueue(); 16151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 16251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 16351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* Process any ValueCells that have been cleared and enqueued by the 16451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski garbage collector. This method should be invoked once by each public 16551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski mutator in this class. We don't invoke this method in public accessors 16651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski because that can lead to surprising ConcurrentModificationExceptions. 16751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 16851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private void processQueue() { 16951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ValueCell vc; 17051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski while ((vc = (ValueCell)queue.poll()) != null) { 17151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (vc.isValid()) hash.remove(vc.key); 17251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski else ValueCell.dropped--; 17351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 17451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 17551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 17651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 17751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* -- Constructors -- */ 17851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 17951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 18051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Construct a new, empty <code>SoftCache</code> with the given 18151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * initial capacity and the given load factor. 18251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 18351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param initialCapacity The initial capacity of the cache 18451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 18551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param loadFactor A number between 0.0 and 1.0 18651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 18751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IllegalArgumentException If the initial capacity is less than 18851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * or equal to zero, or if the load 18951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * factor is less than zero 19051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 19151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public SoftCache(int initialCapacity, float loadFactor) { 19251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski hash = new HashMap(initialCapacity, loadFactor); 19351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 19451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 19551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 19651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Construct a new, empty <code>SoftCache</code> with the given 19751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * initial capacity and the default load factor. 19851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 19951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param initialCapacity The initial capacity of the cache 20051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 20151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IllegalArgumentException If the initial capacity is less than 20251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * or equal to zero 20351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 20451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public SoftCache(int initialCapacity) { 20551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski hash = new HashMap(initialCapacity); 20651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 20751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 20851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 20951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Construct a new, empty <code>SoftCache</code> with the default 21051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * capacity and the default load factor. 21151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 21251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public SoftCache() { 21351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski hash = new HashMap(); 21451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 21551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 21651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 21751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* -- Simple queries -- */ 21851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 21951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 22051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Return the number of key-value mappings in this cache. The time 22151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * required by this operation is linear in the size of the map. 22251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 22351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public int size() { 22451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return entrySet().size(); 22551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 22651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 22751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 22851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Return <code>true</code> if this cache contains no key-value mappings. 22951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 23051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public boolean isEmpty() { 23151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return entrySet().isEmpty(); 23251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 23351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 23451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 23551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Return <code>true</code> if this cache contains a mapping for the 23651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * specified key. If there is no mapping for the key, this method will not 23751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * attempt to construct one by invoking the <code>fill</code> method. 23851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 23951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param key The key whose presence in the cache is to be tested 24051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 24151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public boolean containsKey(Object key) { 24251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return ValueCell.strip(hash.get(key), false) != null; 24351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 24451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 24551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 24651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* -- Lookup and modification operations -- */ 24751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 24851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 24951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Create a value object for the given <code>key</code>. This method is 25051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * invoked by the <code>get</code> method when there is no entry for 25151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>key</code>. If this method returns a non-<code>null</code> value, 25251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * then the cache will be updated to map <code>key</code> to that value, 25351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * and that value will be returned by the <code>get</code> method. 25451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 25551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p> The default implementation of this method simply returns 25651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>null</code> for every <code>key</code> value. A subclass may 25751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * override this method to provide more useful behavior. 25851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 25951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param key The key for which a value is to be computed 26051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 26151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return A value for <code>key</code>, or <code>null</code> if one 26251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * could not be computed 26351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see #get 26451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 26551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski protected Object fill(Object key) { 26651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return null; 26751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 26851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 26951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 27051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Return the value to which this cache maps the specified 27151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>key</code>. If the cache does not presently contain a value for 27251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * this key, then invoke the <code>fill</code> method in an attempt to 27351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * compute such a value. If that method returns a non-<code>null</code> 27451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * value, then update the cache and return the new value. Otherwise, 27551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * return <code>null</code>. 27651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 27751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p> Note that because this method may update the cache, it is considered 27851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * a mutator and may cause <code>ConcurrentModificationException</code>s to 27951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * be thrown if invoked while an iterator is in use. 28051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 28151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param key The key whose associated value, if any, is to be returned 28251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 28351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see #fill 28451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 28551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public Object get(Object key) { 28651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski processQueue(); 28751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Object v = hash.get(key); 28851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (v == null) { 28951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski v = fill(key); 29051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (v != null) { 29151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski hash.put(key, ValueCell.create(key, v, queue)); 29251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return v; 29351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 29451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 29551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return ValueCell.strip(v, false); 29651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 29751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 29851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 29951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Update this cache so that the given <code>key</code> maps to the given 30051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>value</code>. If the cache previously contained a mapping for 30151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>key</code> then that mapping is replaced and the old value is 30251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * returned. 30351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 30451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param key The key that is to be mapped to the given 30551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>value</code> 30651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param value The value to which the given <code>key</code> is to be 30751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * mapped 30851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 30951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return The previous value to which this key was mapped, or 31051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>null</code> if if there was no mapping for the key 31151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 31251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public Object put(Object key, Object value) { 31351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski processQueue(); 31451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ValueCell vc = ValueCell.create(key, value, queue); 31551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return ValueCell.strip(hash.put(key, vc), true); 31651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 31751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 31851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 31951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Remove the mapping for the given <code>key</code> from this cache, if 32051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * present. 32151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 32251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param key The key whose mapping is to be removed 32351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 32451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return The value to which this key was mapped, or <code>null</code> if 32551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * there was no mapping for the key 32651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 32751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public Object remove(Object key) { 32851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski processQueue(); 32951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return ValueCell.strip(hash.remove(key), true); 33051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 33151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 33251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 33351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Remove all mappings from this cache. 33451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 33551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void clear() { 33651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski processQueue(); 33751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski hash.clear(); 33851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 33951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 34051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 34151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* -- Views -- */ 34251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 34351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static boolean valEquals(Object o1, Object o2) { 34451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return (o1 == null) ? (o2 == null) : o1.equals(o2); 34551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 34651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 34751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 34851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* Internal class for entries. 34951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Because it uses SoftCache.this.queue, this class cannot be static. 35051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 35151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private class Entry implements Map.Entry { 35251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private Map.Entry ent; 35351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private Object value; /* Strong reference to value, to prevent the GC 35451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski from flushing the value while this Entry 35551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski exists */ 35651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 35751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Entry(Map.Entry ent, Object value) { 35851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski this.ent = ent; 35951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski this.value = value; 36051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 36151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 36251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public Object getKey() { 36351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return ent.getKey(); 36451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 36551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 36651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public Object getValue() { 36751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return value; 36851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 36951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 37051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public Object setValue(Object value) { 37151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return ent.setValue(ValueCell.create(ent.getKey(), value, queue)); 37251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 37351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 37451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public boolean equals(Object o) { 37551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (! (o instanceof Map.Entry)) return false; 37651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Map.Entry e = (Map.Entry)o; 37751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return (valEquals(ent.getKey(), e.getKey()) 37851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski && valEquals(value, e.getValue())); 37951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 38051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 38151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public int hashCode() { 38251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Object k; 38351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return ((((k = getKey()) == null) ? 0 : k.hashCode()) 38451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ^ ((value == null) ? 0 : value.hashCode())); 38551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 38651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 38751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 38851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 38951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 39051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* Internal class for entry sets */ 39151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private class EntrySet extends AbstractSet { 39251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Set hashEntries = hash.entrySet(); 39351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 39451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public Iterator iterator() { 39551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 39651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return new Iterator() { 39751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Iterator hashIterator = hashEntries.iterator(); 39851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Entry next = null; 39951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 40051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public boolean hasNext() { 40151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski while (hashIterator.hasNext()) { 40251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Map.Entry ent = (Map.Entry)hashIterator.next(); 40351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ValueCell vc = (ValueCell)ent.getValue(); 40451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Object v = null; 40551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if ((vc != null) && ((v = vc.get()) == null)) { 40651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* Value has been flushed by GC */ 40751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski continue; 40851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 40951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski next = new Entry(ent, v); 41051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return true; 41151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 41251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return false; 41351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 41451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 41551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public Object next() { 41651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if ((next == null) && !hasNext()) 41751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new NoSuchElementException(); 41851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Entry e = next; 41951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski next = null; 42051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return e; 42151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 42251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 42351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void remove() { 42451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski hashIterator.remove(); 42551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 42651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 42751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski }; 42851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 42951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 43051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public boolean isEmpty() { 43151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return !(iterator().hasNext()); 43251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 43351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 43451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public int size() { 43551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int j = 0; 43651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (Iterator i = iterator(); i.hasNext(); i.next()) j++; 43751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return j; 43851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 43951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 44051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public boolean remove(Object o) { 44151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski processQueue(); 44251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (o instanceof Entry) return hashEntries.remove(((Entry)o).ent); 44351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski else return false; 44451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 44551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 44651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 44751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 44851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 44951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private Set entrySet = null; 45051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 45151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 45251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Return a <code>Set</code> view of the mappings in this cache. 45351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 45451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public Set entrySet() { 45551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (entrySet == null) entrySet = new EntrySet(); 45651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return entrySet; 45751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 45851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 45951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski} 460