Skip to main content
summaryrefslogblamecommitdiffstats
blob: 60140c420f6156ad69ea0362699647a395102ba9 (plain) (tree)
1
2
3
4
5
6
7
  
                                                                                      



                                                                        
  




                                                   
                                    











                                                                                                                      
  

                       
                                                                                                            
 






                                                                      
               






                                                                    
                                                                                                        












                                                                    
                                                                                                    














                                                                          
                                                                                        






                   


                                                           
                                                                            

   



































































                                                                                           
 
/*
 * Copyright (c) 2007-2009, 2011-2013, 2015 Eike Stepper (Berlin, Germany) and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Eike Stepper - initial API and implementation
 */
package org.eclipse.net4j.util.ref;

import java.lang.ref.ReferenceQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
 * A {@link ConcurrentMap} implementation that uses {@link KeyedReference} instances ({@link KeyedStrongReference},
 * {@link KeyedSoftReference}, {@link KeyedWeakReference} or {@link KeyedPhantomReference}) as its values.
 * <p>
 * A <code>ReferenceValueMap</code> can be used to cache mappings until the <em>value</em> of the mapping is no longer
 * reachable from outside of the map
 * <p>
 * <b>Note:</b> This map is not synchronized. If it is to be used by multiple threads concurrently the user is
 * responsible for applying proper external synchronization!
 *
 * @author Eike Stepper
 */
public abstract class ReferenceValueMap<K, V> extends ReferenceValueMap2<K, V>implements ConcurrentMap<K, V>
{
  public ReferenceValueMap()
  {
    this(new ConcurrentHashMap<K, KeyedReference<K, V>>());
  }

  public ReferenceValueMap(ConcurrentMap<K, KeyedReference<K, V>> map)
  {
    super(map);
  }

  public V putIfAbsent(K key, V value)
  {
    try
    {
      KeyedReference<K, V> ref = createReference(key, value, queue);
      KeyedReference<K, V> oldRef = ((ConcurrentMap<K, KeyedReference<K, V>>)map).putIfAbsent(key, ref);
      return dereference(oldRef);
    }
    finally
    {
      purgeQueue();
    }
  }

  public V replace(K key, V value)
  {
    try
    {
      KeyedReference<K, V> ref = createReference(key, value, queue);
      KeyedReference<K, V> oldRef = ((ConcurrentMap<K, KeyedReference<K, V>>)map).replace(key, ref);
      return dereference(oldRef);
    }
    finally
    {
      purgeQueue();
    }
  }

  public boolean replace(K key, V oldValue, V newValue)
  {
    try
    {
      // TODO Consider a dummy KeyedReference class for oldRef
      KeyedReference<K, V> oldRef = createReference(key, oldValue, queue);
      KeyedReference<K, V> newRef = createReference(key, newValue, queue);
      return ((ConcurrentMap<K, KeyedReference<K, V>>)map).replace(key, oldRef, newRef);
    }
    finally
    {
      purgeQueue();
    }
  }

  public boolean remove(Object key, Object value)
  {
    // TODO Consider a dummy KeyedReference class for value
    return ((ConcurrentMap<K, KeyedReference<K, V>>)map).remove(key, value);
  }

  /**
   * @author Eike Stepper
   */
  public static class Strong<K, V> extends ReferenceValueMap<K, V>
  {
    public Strong()
    {
    }

    public Strong(ConcurrentMap<K, KeyedReference<K, V>> map)
    {
      super(map);
    }

    @Override
    protected KeyedReference<K, V> createReference(K key, V value, ReferenceQueue<V> queue)
    {
      return new KeyedStrongReference<K, V>(key, value);
    }

    @Override
    protected ReferenceQueue<V> createQueue()
    {
      return null;
    }
  }

  /**
   * @author Eike Stepper
   */
  public static class Soft<K, V> extends ReferenceValueMap<K, V>
  {
    public Soft()
    {
    }

    public Soft(ConcurrentMap<K, KeyedReference<K, V>> map)
    {
      super(map);
    }

    @Override
    protected KeyedReference<K, V> createReference(K key, V value, ReferenceQueue<V> queue)
    {
      return new KeyedSoftReference<K, V>(key, value, queue);
    }
  }

  /**
   * @author Eike Stepper
   */
  public static class Weak<K, V> extends ReferenceValueMap<K, V>
  {
    public Weak()
    {
    }

    public Weak(ConcurrentMap<K, KeyedReference<K, V>> map)
    {
      super(map);
    }

    @Override
    protected KeyedReference<K, V> createReference(K key, V value, ReferenceQueue<V> queue)
    {
      return new KeyedWeakReference<K, V>(key, value, queue);
    }
  }
}

Back to the top