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

org.jscsi.utils.SoftHashMap Maven / Gradle / Ivy

The newest version!
/**
 * Copyright (c) 2012, University of Konstanz, Distributed Systems Group 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 Konstanz 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  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.
 */
package org.jscsi.utils;


import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.util.AbstractMap;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;


/**
 * 

SoftHashMap

*

* Based on the SoftHashMap implemented by Dr. Heinz Kabutz. *

*

* Hash map based on soft references. The hash map always makes sure a limited amount of strong references it maintained * in FIFO order to _simulate_ LRU. *

*

* Note that the put and remove methods always return null. *

* * @param Key object of type K. * @param Value object of type V. * */ public final class SoftHashMap extends AbstractMap { /** Default strong reference count. */ private static final int DEFAULT_STRONG_REFERENCE_COUNT = 32; /** The internal HashMap that will hold the SoftReference. */ private final Map> internalMap; /** The number of "hard" references to hold internally. */ private final int strongReferenceCount; /** The FIFO list of strong references, order of last access. */ private V[] strongReferenceArray; /** Current offset of FIFO list. */ private int currentStrongReferenceOffset; /** Reference queue for cleared SoftReference objects. */ private final ReferenceQueue> queue; /** * Default constructor internally using 32 strong references. */ public SoftHashMap () { this(DEFAULT_STRONG_REFERENCE_COUNT); } /** * Constructor that allows to specify how many strong references should be used internally. * * @param initStrongReferenceCount Number of internal strong references. */ @SuppressWarnings ("unchecked") public SoftHashMap (final int initStrongReferenceCount) { internalMap = new HashMap>(); strongReferenceCount = initStrongReferenceCount; strongReferenceArray = (V[]) new Object[initStrongReferenceCount]; currentStrongReferenceOffset = 0; queue = new ReferenceQueue>(); } /** * {@inheritDoc} */ @Override public final V get (final Object key) { V value = null; final SoftReference softReference = internalMap.get(key); if (softReference != null) { // Soft reference was garbage collected. value = softReference.get(); if (value == null) { // Reflect garbage collected soft reference in internal hash // map. internalMap.remove(key); } else { synchronized (strongReferenceArray) { // FIFO on strong references. strongReferenceArray[currentStrongReferenceOffset++] = value; // Assure FIFO does not grow beyond strongReferenceCount. if (currentStrongReferenceOffset >= strongReferenceCount) { currentStrongReferenceOffset = 0; } } } } return value; } /** * {@inheritDoc} */ @Override public final V put (final K key, final V value) { processQueue(); internalMap.put(key, new SoftValue(value, key, queue)); return null; } /** * {@inheritDoc} */ @Override public final V remove (final Object key) { processQueue(); internalMap.remove(key); return null; } /** * {@inheritDoc} */ @Override @SuppressWarnings ("unchecked") public final synchronized void clear () { strongReferenceArray = (V[]) new Object[strongReferenceCount]; processQueue(); internalMap.clear(); } /** * {@inheritDoc} */ @Override public final int size () { processQueue(); return internalMap.size(); } /** * {@inheritDoc} */ @Override public final Set> entrySet () { throw new UnsupportedOperationException(); } /** * Remove garbage collected soft values with the help of the reference queue. */ @SuppressWarnings ({ "rawtypes", "unchecked" }) private final void processQueue () { SoftValue softValue; while ((softValue = (SoftValue) queue.poll()) != null) { internalMap.remove(softValue.key); } } /** * Internal subclass to store keys and values for more convenient lookups. */ private final class SoftValue extends SoftReference { private final K key; /** * Constructor. * * @param initValue Value wrapped as soft reference. * @param initKey Key for given value. * @param initReferenceQueue Reference queue for cleanup. */ @SuppressWarnings ({ "rawtypes", "unchecked" }) private SoftValue (final V initValue, final K initKey, final ReferenceQueue initReferenceQueue) { super(initValue, initReferenceQueue); key = initKey; } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy