package org.cdlib.xtf.util; /* * Copyright (c) 2005, Regents of the University of California * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of the University of California nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /** * A fast but inflexible cache where the keys are integers, the size * is fixed, and a crude LRU policy is enforced. Handles consecutive keys * gracefully. Doesn't support resizing, deletion, or iteration (not that these * operations would be hard, just that they haven't been needed so far.) * * @author Martin Haye */ public class FastIntCache { private int size; private IntHash oldHash; private IntHash newHash; /** * Construct a new cache. Basically, two hash tables are used, each with * the given capacity. When one fills up, the other is thrown out. A * Least-Recently-Used policy is effected by migrating entries from the old * hash to the new hash when they are accessed through get(). * * @param size How large to make each of the two internal hash tables. */ public FastIntCache(int size) { this.size = size; clear(); } // FastCache() /** Clears all entries from the cache */ public void clear() { oldHash = new IntHash(1); newHash = new IntHash(size); } /** Check whether the given key is present in the cache */ public boolean contains(int key) { return newHash.contains(key) || oldHash.contains(key); } /** Retrieve the value for the given key, or null if not found. */ public Object get(int key) { // First, check the new hash Object retVal = newHash.get(key); if (retVal == null) { // Darn. Check the old hash. If it's there, put it into the new hash // since it's been used recently. We don't need to worry about // deleting the old entry, as it will disappear eventually when the // hashes are swapped. // retVal = oldHash.get(key); if (retVal != null) put(key, retVal); } // All done. return retVal; } // get() /** * Add a key/value pair to the cache. May result in pushing older items * out of the cache. */ public void put(int key, Object val) { // If the new hash is full, swap and create a new empty hash. if (newHash.size() >= size) { oldHash = newHash; newHash = new IntHash(size); } // Now that we're sure there's room, put it in the new hash. newHash.put(key, val); } // put() /** * Basic regression test */ public static final Tester tester = new Tester("FastIntCache") { protected void testImpl() { IntHash.tester.test(); FastIntCache cache = new FastIntCache(3); cache.put(1, "a"); cache.put(2, "b"); cache.put(3, "c"); assert cache.contains(1); assert cache.contains(2); assert cache.contains(3); cache.put(4, "d"); assert cache.get(2).equals("b"); cache.put(5, "e"); cache.put(6, "f"); assert !cache.contains(1); assert cache.contains(2); assert cache.contains(5); assert cache.contains(6); } // testImpl() }; } // class FastIntCache