/**
 * Copyright (C) 2012 - present by OpenGamma Inc. and the OpenGamma group of companies
 *
 * Please see distribution for license.
 */
package com.opengamma.util;

import java.lang.ref.WeakReference;
import java.util.WeakHashMap;

/**
 * Reduction of common object values to single instances.
 *
 * @param <T> object type to reduce
 */
public class WeakInstanceCache<T> {

  /**
   * Use a pool of buckets in the way that the concurrent hash works to try and reduce collisions on the monitor.
   */
  private static final int BUCKETS = 1024;

  @SuppressWarnings("unchecked")
  private final WeakHashMap<T, WeakReference<T>>[] _data = new WeakHashMap[BUCKETS];

  public WeakInstanceCache() {
    for (int i = 0; i < BUCKETS; i++) {
      _data[i] = new WeakHashMap<T, WeakReference<T>>();
    }
  }

  protected T getImpl(final WeakHashMap<T, WeakReference<T>> data, final T value) {
    synchronized (data) {
      final WeakReference<T> canonRef = data.get(value);
      if (canonRef != null) {
        final T canonValue = canonRef.get();
        if (canonValue != null) {
          return canonValue;
        }
      }
      data.put(value, new WeakReference<T>(value));
      return value;
    }
  }

  public T get(final T value) {
    final WeakHashMap<T, WeakReference<T>> data = _data[value.hashCode() & (BUCKETS - 1)];
    return getImpl(data, value);
  }

}

@@ -227,16 +227,70 @@
 shMap;%0A%0A
+import com.opengamma.util.async.AbstractHousekeeper;%0A%0A
 /**%0A * R
@@ -345,16 +345,17 @@
 nces.%0A *
+ 
 %0A * @par
@@ -424,16 +424,334 @@
 e%3CT%3E %7B%0A%0A
+  private static final class Housekeeper extends AbstractHousekeeper%3CWeakInstanceCache%3C?%3E%3E %7B%0A%0A    protected Housekeeper(final WeakInstanceCache%3C?%3E target) %7B%0A      super(target);%0A    %7D%0A%0A    @Override%0A    protected boolean housekeep(final WeakInstanceCache%3C?%3E target) %7B%0A      target.gc();%0A      return true;%0A    %7D%0A%0A  %7D%0A%0A
   /**%0A  
@@ -1157,32 +1157,69 @@
 ce%3CT%3E%3E();%0A    %7D%0A
+    (new Housekeeper(this)).start();%0A
   %7D%0A%0A  protected
@@ -1736,16 +1736,16 @@
  - 1)%5D;%0A
-
     retu
@@ -1774,10 +1774,108 @@
 );%0A  %7D%0A%0A
+  protected void gc() %7B%0A    for (int i = 0; i %3C BUCKETS; i++) %7B%0A      _data%5Bi%5D.size();%0A    %7D%0A  %7D%0A%0A
 %7D%0A

Use the housekeeper pattern to tidy up the (empty) weak references that otherwise accumulate after a gc.