org.carrot2.util.pool.SoftUnboundedPool Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of carrot2-mini Show documentation
Show all versions of carrot2-mini Show documentation
Carrot2 search results clustering framework. Minimal functional subset
(core algorithms and infrastructure, no document sources).
/*
* Carrot2 project.
*
* Copyright (C) 2002-2019, Dawid Weiss, Stanisław Osiński.
* All rights reserved.
*
* Refer to the full license file "carrot2.LICENSE"
* in the root folder of the repository checkout or at:
* http://www.carrot2.org/carrot2.LICENSE
*/
package org.carrot2.util.pool;
import java.lang.ref.SoftReference;
import java.util.*;
import java.util.Map.Entry;
import org.carrot2.util.Pair;
import org.carrot2.shaded.guava.common.collect.Maps;
/**
* An extremely simple, unbounded object pool. The pool can provide objects of may types,
* objects get created using parameterless constructors. The pool holds objects using
* {@link SoftReference}s, so they can be garbage collected when memory is needed.
*/
public final class SoftUnboundedPool implements IParameterizedPool
{
private Map, P>, List>> instances = Maps.newHashMap();
private IInstantiationListener instantiationListener;
private IActivationListener activationListener;
private IPassivationListener passivationListener;
private IDisposalListener disposalListener;
public void init(IInstantiationListener objectInstantiationListener,
IActivationListener objectActivationListener,
IPassivationListener objectPassivationListener,
IDisposalListener objectDisposalListener)
{
this.instantiationListener = objectInstantiationListener;
this.activationListener = objectActivationListener;
this.passivationListener = objectPassivationListener;
this.disposalListener = objectDisposalListener;
}
@SuppressWarnings("unchecked")
public I borrowObject(Class clazz, P parameter)
throws InstantiationException, IllegalAccessException
{
I instance = null;
synchronized (this)
{
if (instances == null)
{
throw new IllegalStateException("The pool has already been disposed of");
}
final Pair, P> key = new Pair, P>(
clazz, parameter);
List> list = instances.get(key);
if (list == null)
{
list = new ArrayList>();
instances.put(key, list);
}
while (list.size() > 0 && instance == null)
{
// This cast goes unchecked and can be broken by bad calls, but we shift
// the responsibility to the users of this class.
instance = (I) list.remove(0).get();
}
}
// Not a problem that many threads create new objects for now.
if (instance == null)
{
instance = clazz.newInstance();
if (instantiationListener != null)
{
instantiationListener.objectInstantiated(instance, parameter);
}
}
if (activationListener != null)
{
activationListener.activate(instance, parameter);
}
return instance;
}
public void returnObject(T object, P parameter)
{
if (object == null)
{
return;
}
if (passivationListener != null)
{
passivationListener.passivate(object, parameter);
}
synchronized (this)
{
if (instances == null)
{
return;
}
@SuppressWarnings({
"rawtypes", "unchecked"
})
final Pair key = new Pair(object.getClass(), parameter);
final List> list = instances.get(key);
if (list == null)
{
throw new IllegalStateException(
"Returning an object that was never borrowed: " + object);
}
// The object must not be on the list at this point. The pool won't be large
// enough for the linear scan to be a problem.
for (SoftReference reference : list)
{
final T o = reference.get();
if (o != null && o == object)
{
throw new IllegalStateException("Object has not been borrowed");
}
}
list.add(new SoftReference(object));
}
}
public void dispose()
{
synchronized (this)
{
if (this.instances == null)
{
return;
}
Map, P>, List>> instancesRef = this.instances;
this.instances = null;
for (Entry, P>, List>> entry : instancesRef.entrySet())
{
for (SoftReference reference : entry.getValue())
{
T instance = reference.get();
if (instance != null && disposalListener != null)
{
disposalListener.dispose(instance, entry.getKey().objectB);
}
}
}
}
}
}