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

org.ehcache.util.ConcurrentWeakIdentityHashMap Maven / Gradle / Ivy

There is a newer version: 3.10.8
Show newest version
/*
 * Copyright Terracotta, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.ehcache.util;

import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.util.AbstractMap;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
 * @author Alex Snaps
 */
public class ConcurrentWeakIdentityHashMap implements ConcurrentMap {

  private final ConcurrentMap, V> map = new ConcurrentHashMap, V>();
  private final ReferenceQueue queue = new ReferenceQueue();

  @Override
  public V putIfAbsent(final K key, final V value) {
    purgeKeys();
    return map.putIfAbsent(newKey(key), value);
  }

  @Override
  public boolean remove(final Object key, final Object value) {
    purgeKeys();
    return map.remove(new WeakReference((K) key, null), value);
  }

  @Override
  public boolean replace(final K key, final V oldValue, final V newValue) {
    purgeKeys();
    return map.replace(newKey(key), oldValue, newValue);
  }


  @Override
  public V replace(final K key, final V value) {
    purgeKeys();
    return map.replace(newKey(key), value);
  }

  @Override
  public int size() {
    purgeKeys();
    return map.size();
  }

  @Override
  public boolean isEmpty() {
    purgeKeys();
    return map.isEmpty();
  }

  @Override
  public boolean containsKey(final Object key) {
    purgeKeys();
    return map.containsKey(new WeakReference((K) key, null));
  }

  @Override
  public boolean containsValue(final Object value) {
    purgeKeys();
    return map.containsValue(value);
  }

  @Override
  public V get(final Object key) {
    purgeKeys();
    return map.get(new WeakReference((K) key, null));
  }

  @Override
  public V put(final K key, final V value) {
    purgeKeys();
    return map.put(newKey(key), value);
  }

  @Override
  public V remove(final Object key) {
    purgeKeys();
    return map.remove(new WeakReference((K) key, null));
  }

  @Override
  public void putAll(final Map m) {
    purgeKeys();
    for (Entry entry : m.entrySet()) {
      map.put(newKey(entry.getKey()), entry.getValue());
    }
  }

  @Override
  public void clear() {
    purgeKeys();
    map.clear();
  }

  @Override
  public Set keySet() {
    purgeKeys();
    final HashSet ks = new HashSet();
    for (WeakReference kWeakReference : map.keySet()) {
      final K k = kWeakReference.get();
      if (k != null) {
        ks.add(k);
      }
    }
    return ks;
  }

  @Override
  public Collection values() {
    purgeKeys();
    return map.values();
  }

  @Override
  public Set> entrySet() {
    purgeKeys();
    final HashSet> entries = new HashSet>();
    for (Entry, V> entry : map.entrySet()) {
      final K k = entry.getKey().get();
      if(k != null) {
        entries.add(new AbstractMap.SimpleEntry(k, entry.getValue()));
      }
    }
    return entries;
  }

  private void purgeKeys() {
    Reference reference;
    while ((reference = queue.poll()) != null) {
      map.remove(reference);
    }
  }

  private WeakReference newKey(final K key) {
    return new WeakReference(key, queue);
  }

  private static class WeakReference extends java.lang.ref.WeakReference {

    private final int hashCode;

    private WeakReference(final T referent, final ReferenceQueue q) {
      super(referent, q);
      hashCode = referent.hashCode();
    }

    @Override
    public boolean equals(final Object obj) {
      return obj != null && obj.getClass() == this.getClass() && (this == obj || this.get() == ((WeakReference)obj).get());
    }

    @Override
    public int hashCode() {
      return hashCode;
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy