Mega Code Archive

 
Categories / Java / Development Class
 

Map implementation for cache usage

/*  * This file is part of aion-emu <aion-emu.com>.  *  *  aion-emu is free software: you can redistribute it and/or modify  *  it under the terms of the GNU General Public License as published by  *  the Free Software Foundation, either version 3 of the License, or  *  (at your option) any later version.  *  *  aion-emu is distributed in the hope that it will be useful,  *  but WITHOUT ANY WARRANTY; without even the implied warranty of  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the  *  GNU General Public License for more details.  *  *  You should have received a copy of the GNU General Public License  *  along with aion-emu.  If not, see <http://www.gnu.org/licenses/>.  */ //package com.aionemu.gameserver.utils.collections.cachemap; import java.lang.ref.Reference; import java.lang.ref.ReferenceQueue; import java.lang.ref.SoftReference; import java.util.HashMap; import java.util.Map; /**  * This class is a simple map implementation for cache usage.<br>  * <br>  * Value may be stored in map really long, but it for sure will be removed if there is low memory (and of course there  * isn't any strong reference to value object)  *   * @author Luno  */ class SoftCacheMap<K, V> extends AbstractCacheMap<K, V> implements CacheMap<K, V> {   /**    * This class is a {@link SoftReference} with additional responsibility of holding key object    *     * @author Luno    */   private class SoftEntry extends SoftReference<V>   {     private K  key;     SoftEntry(K key, V referent, ReferenceQueue<? super V> q)     {       super(referent, q);       this.key = key;     }     K getKey()     {       return key;     }   }   SoftCacheMap(String cacheName, String valueName)   {     super(cacheName, valueName);   }   @SuppressWarnings("unchecked")   @Override   protected synchronized void cleanQueue()   {     SoftEntry en = null;     while ((en = (SoftEntry) refQueue.poll()) != null)     {       K key = en.getKey();       cacheMap.remove(key);     }   }   @Override   protected Reference<V> newReference(K key, V value, ReferenceQueue<V> vReferenceQueue)   {     return new SoftEntry(key, value, vReferenceQueue);   } } /**  * Base class for {@link WeakCacheMap} and {@link SoftCacheMap}  *   * @author Luno  *   * @param <K>  * @param <V>  */ abstract class AbstractCacheMap<K, V> implements CacheMap<K, V> {   protected final String          cacheName;   protected final String          valueName;   /** Map storing references to cached objects */   protected final Map<K, Reference<V>>  cacheMap  = new HashMap<K, Reference<V>>();   protected final ReferenceQueue<V>    refQueue  = new ReferenceQueue<V>();   /**    * @param cacheName    * @param valueName    */   AbstractCacheMap(String cacheName, String valueName)   {     this.cacheName = "#CACHE  [" + cacheName + "]#  ";     this.valueName = valueName;   }   /** {@inheritDoc} */   @Override   public void put(K key, V value)   {     cleanQueue();     if (cacheMap.containsKey(key))       throw new IllegalArgumentException("Key: " + key + " already exists in map");     Reference<V> entry = newReference(key, value, refQueue);     cacheMap.put(key, entry);   }   /** {@inheritDoc} */   @Override   public V get(K key)   {     cleanQueue();     Reference<V> reference = cacheMap.get(key);     if (reference == null)       return null;     V res = reference.get();     return res;   }   @Override   public boolean contains(K key)   {     cleanQueue();     return cacheMap.containsKey(key);   }   protected abstract void cleanQueue();   @Override   public void remove(K key)   {     cacheMap.remove(key);   }   protected abstract Reference<V> newReference(K key, V value, ReferenceQueue<V> queue); } interface CacheMap<K, V> {   /**    * Adds a pair <key,value> to cache map.<br>    * <br>    *     * <font color='red'><b>NOTICE:</b> </font> if there is already a value with given id in the map,    * {@link IllegalArgumentException} will be thrown.    *     * @param key    * @param value    */   public void put(K key, V value);   /**    * Returns cached value correlated to given key.    *     * @param key    * @return V    */   public V get(K key);   /**    * Checks whether this map contains a value related to given key.    * @param key    * @return true or false    */   public boolean contains(K key);   /**    * Removes an entry from the map, that has given key.    * @param key    */   public void remove(K key); }