SoftSmartCache.java :  » Net » Mondrian-3.2.0 » mondrian » rolap » cache » Java Open Source

Java Open Source » Net » Mondrian 3.2.0 
Mondrian 3.2.0 » mondrian » rolap » cache » SoftSmartCache.java
/*
// This software is subject to the terms of the Eclipse Public License v1.0
// Agreement, available at the following URL:
// http://www.eclipse.org/legal/epl-v10.html.
// Copyright (C) 2004-2005 TONBELLER AG
// Copyright (C) 2006-2009 Julian Hyde
// All Rights Reserved.
// You must accept the terms of that agreement to use this software.
*/
package mondrian.rolap.cache;

import mondrian.util.Pair;

import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.util.*;

/**
 * A map with soft references that is cleaned up in regular intervals.
 * <p>
 * There is no contains(key) method because it makes no sense - after
 * contains() returns true, the garbage collector may remove
 * the value that was contained. Instead the code should call get() and
 * keep a reference to the value to prevent garbage collection.
 *
 * @author av
 * @since Nov 3, 2005
 * @version $Id: //open/mondrian-release/3.2/src/main/mondrian/rolap/cache/SoftSmartCache.java#1 $
 */
public class SoftSmartCache<K, V> implements SmartCache<K, V> {

    private final Map<K, CacheReference> cache =
        new HashMap<K, CacheReference>();

    private final ReferenceQueue<V> queue = new ReferenceQueue<V>();

    /**
     * an entry in the cache that contains the key for
     * the cache map to remove the entry when its value
     * has been garbage collected
     *
     * @author rk
     * @since Nov 7, 2005
     */
    class CacheReference extends SoftReference<V> {
        K key;

        public CacheReference(K key, V value) {
            super(value, queue);
            this.key = key;
        }

        public String toString() {
            return String.valueOf(get());
        }
    }

    /* (non-Javadoc)
     * @see mondrian.rolap.cache.SmartCache#put(java.lang.Object, java.lang.Object)
     */
    public synchronized V put(K key, V value) {
        // remove garbage collected entries from cache
        CacheReference ref;
        while ((ref = (CacheReference) queue.poll()) != null) {
            cache.remove(ref.key);
        }

        // put new entry into cache
        ref = new CacheReference(key, value);
        ref = cache.put(key, ref);
        if (ref != null) {
            return ref.get();
        }
        return null;
    }

    /* (non-Javadoc)
     * @see mondrian.rolap.cache.SmartCache#get(java.lang.Object)
     */
    public synchronized V get(K key) {
        CacheReference ref = cache.get(key);
        if (ref == null) {
            return null;
        }
        V value = ref.get();
        if (value == null) {
            cache.remove(key);
        }
        return value;
    }

    /* (non-Javadoc)
     * @see mondrian.rolap.cache.SmartCache#clear()
     */
    public void clear() {
        cache.clear();
    }

    /* (non-Javadoc)
     * @see mondrian.rolap.cache.SmartCache#size()
     */
    public int size() {
        return cache.size();
    }

    public Iterator<Map.Entry<K, V>> iterator() {
        final Iterator<Map.Entry<K, CacheReference>> cacheIterator =
            cache.entrySet().iterator();
        return new Iterator<Map.Entry<K, V>>() {
            private Map.Entry<K, V> entry;

            public boolean hasNext() {
                if (entry != null) {
                    return true;
                }
                while (cacheIterator.hasNext()) {
                    Map.Entry<K, CacheReference> cacheEntry =
                        cacheIterator.next();
                    // skip over entries that have been garbage collected
                    final V value = cacheEntry.getValue().get();
                    if (value != null) {
                        // Would use AbstractMap.SimpleEntry but it's not public
                        // until JDK 1.6.
                        entry = new Pair<K, V>(cacheEntry.getKey(), value);
                        return true;
                    }
                }
                return false;
            }

            public Map.Entry<K, V> next() {
                Map.Entry<K, V> entry = this.entry;
                this.entry = null;
                return entry;
            }

            public void remove() {
                cacheIterator.remove();
            }
        };
    }
}

// End SoftSmartCache.java

java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.